" ===============================================================
" Vim Plugin for Verilog Code Automactic Generation&Check
" Language:     Verilog
" Maintainer:   Snowind
" Version:      1.0
" Last Update:  ...01/25/2022,Snowind
" For version 7.x or above
" ===============================================================
" Notice, template:
" 	module design (/*AUTOARG*);
" 	always @(/*AUTOSENSE*/)
" 	/*AUTOINST*/
" 	/*AUTODEFINES*/
" 	/*AUTOPORTS*/
" 	/*AUTOREG*/


if version < 700
   finish
endif

if exists("b:vlog_auto_plugin") && b:vlog_auto_plugin == 1
	finish
endif

if exists("b:current_syntax")
	if b:current_syntax != "verilog"
		finish
	endif
endif

let b:vlog_auto_plugin = 1

"SNOTE_BEG ...01/25/2022,Snowind, # Enable scripts debug
let b:dbg=0
if exists("b:dbg") && b:dbg==1
	redir! > test_debug.v
	silent echo " Debug Info:"	
	redir END
endif


"Variables need to be defined
let s:VERILOG_Company = 'COMPANY'
let s:VERILOG_Project = 'PROJECT'
let s:VERILOG_AuthorName = ''
if exists("g:COMPANY") && g:COMPANY != ""
	let s:VERILOG_Company = g:COMPANY
endif
if exists("g:PROJECT") && g:PROJECT != ""
	let s:VERILOG_Project = g:PROJECT
endif
if exists("g:AUTHOR") && g:AUTHOR != ""
	let s:VERILOG_AuthorName= g:AUTHOR
endif

let s:VERILOG_Cmt_str = '//'
" header line num for AutoTemplate"
let s:header_line_num = 0


iabbrev <= <= #`FFD
"iabbrev <= <= #1

" variables
if exists("s:VERILOG_Max_Col") == 0
   let s:VERILOG_Max_Col = 40
endif
if exists("s:VERILOG_Arg_Margin") == 0
   let s:VERILOG_Arg_Margin = "    "
endif
if exists("s:VERILOG_Inst_Margin") == 0
   let s:VERILOG_Inst_Margin = "    "
endif
if exists("s:VERILOG_Indent_Width")
   let b:vlog_ind = s:VERILOG_Indent_Width
   let b:indent = repeat(' ',b:vlog_ind)
else
   let b:vlog_ind = 4
   let b:indent = repeat(' ',b:vlog_ind)
endif
if exists("s:VERILOG_Autodef_Max_Len") == 0
	let s:VERILOG_Autodef_Max_Len = 39
endif
if exists("s:VERILOG_Autoinst_Prefix_Max_Len") == 0
	let s:VERILOG_Autoinst_Prefix_Max_Len = 26
endif
if exists("s:VERILOG_Autoinst_Suffix_Max_Len") == 0
	let s:VERILOG_Autoinst_Suffix_Max_Len = 30
endif

let s:sig_offset = 13
let s:clk_period = 8
let s:clk_num = 12
let b:cq_trans = 1
let b:wave_max_wd = s:sig_offset + s:clk_num*s:clk_period
"0 is clk posedge, 4 is clk negedge

" Menus
amenu &Verilog.-Add-                           :
amenu &Verilog.&AddClk                         :call AddClk()<CR>
amenu &Verilog.&AddSig                         :call AddSig()<CR>
amenu &Verilog.&AddBus                         :call AddBus()<CR>
amenu &Verilog.&AddBlk                         :call AddBlk()<CR>
amenu &Verilog.-Operation-                     :
amenu &Verilog.&Invert\ \ \ <F8>               :call Invert()<CR>
amenu &Verilog.&Header                      	 :call AddHeader()<CR>

amenu &Verilog.-Automatic-                  :
amenu &Verilog.Auto&Template                :call AutoTemplate()<CR>
amenu &Verilog.Auto&Arg\ \ \ <S-F1>         :call AutoArg()<CR>
amenu &Verilog.Auto&Def\ \ \ <S-F2>         :call AutoDef()<CR>
amenu &Verilog.Auto&Inst\ \ <S-F3>          :call AutoInst()<CR>
amenu &Verilog.Auto&UpdateLastModifyTime		:call UpdateLastModifyTime()<CR>
"amenu &Verilog.Auto&Sense                   :call AutoSense()<CR>
"amenu &Verilog.Auto&Reg                     :call AutoReg()<CR>

amenu &Verilog.-Inst-                   		:
amenu &Verilog.ShowInst											:call ShowInst()<CR>
amenu &Verilog.GotoInst											:call GotoInst()<CR>
amenu &Verilog.GotoInstFile									:call GotoInstFile()<CR>

"amenu &Verilog.GetInsts											:call GetInsts()<CR>
"amenu &Verilog.GetAllParas									:call GetAllParas()<CR>
"amenu &Verilog.GetAllDefs										:call GetAllDefs()<CR>

"amenu &Verilog.-QuickCheck-	            :
"amenu &Verilog.Report\ No\ Loading/Driving\ nets :call AutoCheck()<CR>

amenu &Verilog.-Comment-                   :
amenu &Verilog.&AutoComment                :call AutoComment()<CR>
amenu &Verilog.&AutoComment2               :call AutoComment2()<CR>
"amenu &Verilog.&searchComment							 :call SearchComment()<CR>

amenu &Verilog.-Kill-                       :
amenu &Verilog.&KillAuto                    :call KillAuto()<CR>
amenu &Verilog.KillAutoArg                  :call KillAutoArg()<CR>
amenu &Verilog.KillAutoDef                  :call KillAutoDef()<CR>
amenu &Verilog.KillAutoInst                 :call KillAutoInst()<CR>
"amenu &Verilog.KillAutoSense                :call KillAutoSense()<CR>
"amenu &Verilog.KillAutoReg                  :call KillAutoReg()<CR>

command AutoArg                             :call AutoArg()
command AutoDef                             :call AutoDef()
command AutoInst                            :call AutoInst()
command KillAuto                            :call KillAuto()
command KillAutoArg                         :call KillAutoArg()
command KillAutoDef                         :call KillAutoDef()
command KillAutoInst                        :call KillAutoInst()

command ShowInst                            :call ShowInst()
command GotoInst                            :call GotoInst()
map <C-J>                                   :ShowInst<ESC>
map <C-K>                                   :GotoInst<ESC>
map <S-F1>                                  :AutoArg<ESC>
map <S-F2>                                  :AutoDef<ESC>
map <S-F3>                                  :AutoInst<ESC>
"map <F8>                                    :call Zh_test()<ESC>
"map <F2>                                    :call AutoComment()<ESC>
"map <F3>                                    <ESC>:call AutoComment2()<ESC>

"autocmd BufNewFile *.v call AutoTemplate()
"autocmd BufWrite *.v call UpdateLastModifyTime()
"autocmd BufWritePre *.v call UpdateLastModifyTime()

"========================================
" Functions
"========================================
" Wavefrom: add clk 
function AddClk()
	let ret = []
	let ret0 = "//  .   .   ."
	let ret1 = "//          +"
	let ret2 = "// clk      |"
	let ret3 = "//          +"
	let format = '%' . s:clk_period/2 . 'd'
	for idx in range(1,s:clk_num)
		let ret0 = ret0 . printf(format,idx) . repeat(' ',s:clk_period/2)
		for idx2 in range(1,s:clk_period/2-1)
			let ret1 = ret1 . '-'
			let ret2 = ret2 . ' '
			let ret3 = ret3 . ' '
		endfor
		let ret1 = ret1 . '+'
		let ret2 = ret2 . '|'
		let ret3 = ret3 . '+'
		for idx2 in range(1,s:clk_period/2-1)
			let ret1 = ret1 . ' '
			let ret2 = ret2 . ' '
			let ret3 = ret3 . '-'
		endfor
		let ret1 = ret1 . '+'
		let ret2 = ret2 . '|'
		let ret3 = ret3 . '+'
	endfor
	call add(ret,ret0)
	call add(ret,ret1)
	call add(ret,ret2)
	call add(ret,ret3)
	call append(line("."),ret)
endfunction

" Wavefrom: add signal
function AddSig()
	let ret = []
	let ret0 = "//          "
	let ret1 = "// sig      "
	let ret2 = "//          "
	for idx in range(s:sig_offset,b:wave_max_wd)
		let ret0 = ret0 . " "
		let ret1 = ret1 . " "
		let ret2 = ret2 . "-"
	endfor
	call add(ret,ret0)
	call add(ret,ret1)
	call add(ret,ret2)
	call append(line("."),ret)
endfunction

" Wavefrom: add bus
function AddBus()
	let ret = []
	let ret0 = "//          "
	let ret1 = "// bus      "
	let ret2 = "//          "
	for idx in range(s:sig_offset,b:wave_max_wd)
		let ret0 = ret0 . "-"
		let ret1 = ret1 . " "
		let ret2 = ret2 . "-"
	endfor
	call add(ret,ret0)
	call add(ret,ret1)
	call add(ret,ret2)
	call append(line("."),ret)
endfunction

function AddBlk()
	let ret = []
	let ret0 = "//          "
	for idx in range(s:sig_offset,b:wave_max_wd)
		let ret0 = ret0 . " "
	endfor
	call add(ret,ret0)
	call append(line("."),ret)
endfunction

function My_mod(int1,int2)
	let ret = a:int1
	while 1
		if ret >= a:int2
			let ret = ret - a:int2
		else
			break
		endif
	endwhile
	return ret
endfunction
function GetSigNameLineNum()
	let lnum = -1
	let cur_lnum = line(".")
	if getline(cur_lnum) =~ '^\/\/\s*\w\+'
		let lnum = cur_lnum
	elseif getline(cur_lnum-1) =~ '^\/\/\s*\w\+'
		let lnum = cur_lnum-1
	elseif getline(cur_lnum+1) =~ '^\/\/\s*\w\+'
		let lnum = cur_lnum+1
	endif
	return lnum
endfunction

function GetPosedge()
	return col(".") - My_mod(col(".") - s:sig_offset,s:clk_period)
endfunction
function GetNegedge()
	return GetPosedge() + s:clk_period/2
endfunction

function SigLastClkIsHigh()
	let ret = 0
	let lnum = GetSigNameLineNum()
	if lnum != -1
		let posedge = GetPosedge()
		let negedge = GetNegedge()
		let line = getline(lnum - 1)
		if line[posedge-1] =~ '-'
			let ret = 1
		endif
	endif
	return ret
endfunction

function SigCurClkIsHigh()
	let ret = 0
	let lnum = GetSigNameLineNum()
	if lnum != -1
		let posedge = GetPosedge()
		let negedge = GetNegedge()
		let line = getline(lnum - 1)
		if line[negedge-1] =~ '-'
			let ret = 1
		endif
	endif
	return ret
endfunction

function SigNextClkIsHigh()
	let ret = 0
	let lnum = GetSigNameLineNum()
	if lnum != -1
		let posedge = GetPosedge()
		let negedge = GetNegedge()
		let line = getline(lnum - 1)
		if line[negedge+8-1] =~ '-'
			let ret = 1
		endif
	endif
	return ret
endfunction

function BusCurClkHaveChg()
	let ret = 0
	let lnum = GetSigNameLineNum()
	if lnum != -1
		let posedge = GetPosedge()
		let line = getline(lnum)
		if line[posedge+b:cq_trans-1] =~ 'X'
			let ret = 1
		endif
	endif
	return ret
endfunction

function Invert()
	let last = SigLastClkIsHigh()
	let cur = SigCurClkIsHigh()
	let next = SigNextClkIsHigh()
	let chg	= BusCurClkHaveChg()

	let lnum = GetSigNameLineNum()
	let top = getline(lnum-1)
	let mid = getline(lnum)
	let bot = getline(lnum+1)

	let posedge = GetPosedge()
	let negedge = GetNegedge()
	let next_posedge = posedge + s:clk_period

	let res_top = strpart(top,0,posedge+b:cq_trans-1)
	let res_mid = strpart(mid,0,posedge+b:cq_trans-1)
	let res_bot = strpart(bot,0,posedge+b:cq_trans-1)

	let init_top_char = ' '
	let init_mid_char = ' '
	let init_bot_char = ' '
	let top_char = ' '
	let mid_char = ' '
	let bot_char = ' '
	let is_bus = 0

	if top[negedge] =~ '-' && bot[negedge] =~ '-'
		let is_bus = 1
		if chg
			let init_top_char = '-'
			let init_mid_char = ' '
			let init_bot_char = '-'
		else
			let init_top_char = ' '
			let init_mid_char = 'X'
			let init_bot_char = ' '
		endif
		let top_char = '-'
		let mid_char = ' '
		let bot_char = '-'
		let res_top = res_top . init_top_char
		let res_mid = res_mid . init_mid_char
		let res_bot = res_bot . init_bot_char
		for idx in range(1,s:clk_period-1)
			let res_top = res_top . top_char
			let res_mid = res_mid . mid_char
			let res_bot = res_bot . bot_char
		endfor
	else
		if last == cur
			if cur
				let init_top_char = '+'
				let init_mid_char = '|'
				let init_bot_char = '+'
				let top_char = ' '
				let bot_char = '-'
			else
				let init_top_char = '+'
				let init_mid_char = '|'
				let init_bot_char = '+'
				let top_char = '-'
				let bot_char = ' '
			endif
		else
			if cur
				let init_top_char = ' '
				let init_mid_char = ' '
				let init_bot_char = '-'
				let top_char = ' '
				let bot_char = '-'
			else
				let init_top_char = '-'
				let init_mid_char = ' '
				let init_bot_char = ' '
				let top_char = '-'
				let bot_char = ' '
			endif
		endif

		let res_top = res_top . init_top_char
		let res_mid = res_mid . init_mid_char
		let res_bot = res_bot . init_bot_char
		for idx in range(1,s:clk_period-1)
			let res_top = res_top . top_char
			let res_mid = res_mid . mid_char
			let res_bot = res_bot . bot_char
		endfor

		if next == cur 
			let init_top_char = '+'
			let init_mid_char = '|'
			let init_bot_char = '+'
		else
			if cur
				let init_top_char = ' '
				let init_mid_char = ' '
				let init_bot_char = '-'
			else
				let init_top_char = '-'
				let init_mid_char = ' '
				let init_bot_char = ' '
			endif
		endif
		let res_top = res_top . init_top_char
		let res_mid = res_mid . init_mid_char
		let res_bot = res_bot . init_bot_char
	endif

	let res_top = res_top .strpart(top,posedge+b:cq_trans+s:clk_period-is_bus,b:wave_max_wd-1)
	let res_mid = res_mid .strpart(mid,posedge+b:cq_trans+s:clk_period-is_bus,b:wave_max_wd-1)
	let res_bot = res_bot .strpart(bot,posedge+b:cq_trans+s:clk_period-is_bus,b:wave_max_wd-1)

	call setline(lnum-1,res_top)
	call setline(lnum,res_mid)
	call setline(lnum+1,res_bot)
endfunction

function AutoComment()
	let lnum = line(".")
	let line = getline(lnum)
	if line =~ '^\/\/'
		let tmp_line = substitute(line,'^\/\/','','')
	else
		let tmp_line = s:VERILOG_Cmt_str . line
	endif
	call setline(lnum,tmp_line)
endfunction

function AutoComment2()
	if line("'<") <= line(".") && line("'>") >= line(".")
		if getline(line("'<")) =~ '^/\*'
			'<
			execute "normal dd"
			'>
			execute "normal dd"
		else
			call append(line("'<")-1,"/****************************************************************")
			call append(line("'>")  ,"****************************************************************/")
		endif
	endif
	"echo "< = " . line("'<") . " > = " . line("'>") . " cur = " . line(".")
endfunction

function Zh_test()
"	let lnum = GetSigNameLineNum()
"	if lnum != -1
"		echo getline(lnum)
"	else
"		echo "not sig line"
"	endif
"
"	let last = SigLastClkIsHigh()
"	let cur = SigCurClkIsHigh()
"	let next = SigNextClkIsHigh()
"	echo "last = " . last . " cur = " . cur . " next = " . next
"	echo "pos = " . GetPosedge() . " nes = " . GetNegedge()
"
	call Invert()
endfunction
"===============================================================
"        Add File Header
"===============================================================
" insert line_str to line_no and incr"
function Append_line(line_str)
	"if a:line_num != "":
	"	let b:header_line_num = a:line_num
	"else
	"if !exists(s:header_line_num)
	"	let s:header_line_num = 0
	"	"let b:header_line_num = line(".")
	"endif
	"echo "- DBG line:".s:header_line_num
	"
	call append(s:header_line_num, a:line_str)
	let s:header_line_num = s:header_line_num + 1
endfunction

function AddHeader()
	let filename = expand("%")
	let modulename = matchstr(filename,'\w\+')
	call Append_line(s:VERILOG_Cmt_str . "//////////////////////////////////////////////////////////////////////////")
	call Append_line(s:VERILOG_Cmt_str . "// Copyright (c) ".strftime("%Y ").s:VERILOG_Company.". All rights reserved.")
	call Append_line(s:VERILOG_Cmt_str . "// ")
	call Append_line(s:VERILOG_Cmt_str . "// This file and associated deliverables are the trade secrets,")
	call Append_line(s:VERILOG_Cmt_str . "// confidential information and copyrighted works of ".s:VERILOG_Company." Corporation,")
	call Append_line(s:VERILOG_Cmt_str . "// and are subject to your license agreement with ".s:VERILOG_Company.".")
	call Append_line(s:VERILOG_Cmt_str . "//")
	call Append_line(s:VERILOG_Cmt_str . "// Use of these deliverables for the purpose of making silicon from an IC")
	call Append_line(s:VERILOG_Cmt_str . "// design is limited to the terms and conditions of your license agreement")
	call Append_line(s:VERILOG_Cmt_str . "// with ".s:VERILOG_Company." If you have further questions please contact ".s:VERILOG_Company.".")
	call Append_line(s:VERILOG_Cmt_str . "//------------------------------------------------------------------------")
	call Append_line(s:VERILOG_Cmt_str . "// File       :  ".filename)
	call Append_line(s:VERILOG_Cmt_str . "// Project    :  ".s:VERILOG_Project)
	call Append_line(s:VERILOG_Cmt_str . "// Module			:  ".modulename)
	call Append_line(s:VERILOG_Cmt_str . "// Author     :  ".s:VERILOG_AuthorName)
	call Append_line(s:VERILOG_Cmt_str . "// Create On  :  ".strftime("%m/%d/%Y %H:%M"))
	call Append_line(s:VERILOG_Cmt_str . "// Description:")
	call Append_line(s:VERILOG_Cmt_str . "//")
	call Append_line(s:VERILOG_Cmt_str . "// Revision		:  $Revision:$")
	call Append_line(s:VERILOG_Cmt_str . "// Checked in :  $DateTime:$")
	call Append_line(s:VERILOG_Cmt_str . "// Modified by:  $Author:$")
	call Append_line(s:VERILOG_Cmt_str . "// Change     :  $Change:$")
	call Append_line(s:VERILOG_Cmt_str . "//")
	call Append_line(s:VERILOG_Cmt_str . "// $Id:$")
	call Append_line(s:VERILOG_Cmt_str . "//////////////////////////////////////////////////////////////////////////")

endfunction

function AutoTemplate()
	let filename = expand("%")
	let modulename = matchstr(filename,'\w\+')
	call AddHeader()
	call Append_line("module " . modulename . '(/*autoarg*/);')
	if modulename == 'top'
		call Append_line("")
		call Append_line("reg clk;")
		call Append_line("reg rst_n;")
		call Append_line("")
		call Append_line("/*autodef off*/")
		call Append_line("initial begin")
		call Append_line("  clk = 1'b0;")
		call Append_line("  forever #10 clk = ~clk;")
		call Append_line("end")
		call Append_line("")
		call Append_line("initial begin")
		call Append_line("  rst_n = 1'b0;")
		call Append_line("  #52 rst_n = 1'b1;")
		call Append_line("end")
		call Append_line("")
		call Append_line("initial begin")
		call Append_line("  $vcdpluson(0,top);")
		call Append_line("end")
		call Append_line("")
		call Append_line("initial begin")
		call Append_line("  #1000;")
		call Append_line("  $finish;")
		call Append_line("end")
		call Append_line("")
		call Append_line("/*autodef on*/")
		call Append_line("")
		call Append_line('/*autodef*/')
		call Append_line("")
		call Append_line("//inst u_inst(/*autoinst*/);")
		call Append_line("")
		call Append_line("")
		call Append_line("endmodule")
		call search('inst')
	else
		call Append_line("")
		call Append_line("input    clk;")
		call Append_line("input    rst_n;")
		call Append_line("output   data;")
		call Append_line("inout		 data_oen;")
		call Append_line("")
		call Append_line('/*autodef*/')
		call Append_line("")
		call Append_line("endmodule")
		call search('clk')
	endif
endfunction

function UpdateLastModifyTime()
	let line = getline(6)
	if line =~ '// Last Modified'
		call setline(6,"// Last Modified : " . strftime("%Y-%m-%d %H:%M"))
	endif
endfunction

function ShowInst()
	" first lnum is 1, and first col is 1
	let lnum = line(".")
	let curcol = col(".")
	let line = getline(lnum)
	if line =~ '\<autoinst\>'
		call ShowInstWrapper(0,lnum,'')
		return
	endif
	"if curcol char is not a word char
	if line[curcol-1] !~ '\w'
		call ShowInstWrapper(0,lnum,'')
		return
	else
		if SearchComment(lnum,curcol)
			call ShowInstWrapper(0,lnum,'')
			return
		endif

		let word = GetCursorWord(line,curcol)

		"mask key words
		if word =~ '\(\<input\>\|\<output\>\|\<inout\>\|\<wire\>\|\<reg\>\|\<function\>\|\<endfunction\>\|\<task\>\|\<endtask\>\|\<module\>\|\<endmodule\>\)'
			call ShowInstWrapper(0,lnum,'')
			return
		endif

		let ret = match(line,'\.\s*'. word)
		if ret != -1
			let ret = matchend(line,'\.\s*'. word)
			"curcol is in '.word'
			if ret >= curcol
				call ShowInstWrapper(1,lnum,word)
			else
				call ShowInstWrapper(2,lnum,word)
			endif
		else
			call ShowInstWrapper(2,lnum,word)
		endif
	endif
endfunction

function GotoInst()
	" first lnum is 1, and first col is 1
	let lnum = line(".")
	let curcol = col(".")

	"match() get idx of line
	if SearchComment(lnum,curcol)
		echohl ErrorMsg | echo "========GotoInst() fail cause comment=========" | echohl None
		return
	endif

	let line = getline(lnum)
	if line =~ '\<autoinst\>'
		"echohl ErrorMsg | echo "========GotoInst() ok0=========" | echohl None
		call GotoInstFile(GetInstName(line),'')
		return
	endif

	if line !~ '^\s*\.\w'
		echohl ErrorMsg | echo "========GotoInst() fail cause not .inst_port line=========" | echohl None
		return
	else
		"echohl ErrorMsg | echo "========GotoInst() ok1=========" | echohl None
		call GotoInstFile(GetInstName(getline(GetInstLineNum(lnum))),GetPortName(line))
	endif

endfunction

function GotoInstFile(inst,port)
	if GetInstFileName(a:inst) == ''
		echohl ErrorMsg | echo "file: tags not exist or need update!" | echohl None
		echo ""
		return
	endif
	execute "tag " . a:inst
	call search('\^\s*module\s\+\w')
	if a:port != ''
		call search('^\s*\(\<input\>\|\<output\>\|\<inout\>\)\s*\(\<wire\>\|\<reg\>\)*\s*\(\[.*:.*\]\)*\s*' . a:port)
		call search('\<' . a:port . '\>')
	endif
	execute "normal zz"
endfunction

function SearchComment(lnum,curcol)
	" 1 found, 0 no found
	"echo "SearchComment ing...."

	"search comment //
	let ret = match(getline(a:lnum),'\/\/')
	if ret != -1
		if ret < a:curcol-1
			return 1
		endif
	endif

	"search comment /* ... */
	for idx in range(a:lnum,1,-1)
		let line = getline(idx)
		"echo line

		"get all start and end ret
		let se_rets = []
 		let times = 1
 		while 1
 			let ret = match(line,'\(\/\*\|\*\/\)',0,times)
 			if ret == -1
 				break
 			else
				if line[ret] == '/'
					call extend(se_rets,[{'s':ret}])
				else
					call extend(se_rets,[{'e':ret}])
				endif

				"echo "pos: " . ret . " char = " . line[ret]
 				let times = times + 1
 			endif
 		endwhile
		if len(se_rets) == 0
			continue
		endif

		"have found '/*' or '*/'
		"start match
		let s_ret = -1
		let e_ret = -1
		let s_key = 's'
		let e_key = 's'

		if idx != a:lnum
			"no cur line, only care the last se_ret
			let se_ret = se_rets[len(se_rets)-1]
			for ret in keys(se_ret)
				let e_key = ret
			endfor
			if e_key == 's'
				"echo "====   /* ... curcol"
				return 1
			endif
		else
			"cur line
			"get near two ret beside a:curcol, result is s_ret < a:curcol < e_ret
			let break_list_loop = 0
			for se_ret in se_rets
				for ret in keys(se_ret)
					"echo ret . ":" . se_ret[ret]
					if se_ret[ret] < a:curcol-1
						let s_ret = se_ret[ret]
						let s_key = ret
					else
						let e_ret = se_ret[ret]
						let e_key = ret
						let break_list_loop = 1
					endif
				endfor
				if break_list_loop == 1
					break
				endif
			endfor
			"echo "result s_ret:e_ret = " . s_ret . ":" . e_ret
			"echo "result s_key:e_key= " . s_key . ":" . e_key
			if s_ret == -1 && e_ret == -1
				echo "Fatal error!"
			elseif s_ret == -1 && e_ret != -1
				if e_key == 'e'
					"echo "====  ad curcol ... */"
					return 1
				endif
			elseif s_ret != -1 && e_ret == -1
				if s_key == 's'
					"echo "====   /* ... curcol"
					return 1
				endif
			elseif s_ret != -1 && e_ret != -1
				"only two result  /* ... curcol ... */ and  */ ... curcol ... /*
				if s_key == 's'
					"echo "====   /* ... curcol ... */"
					return 1
				endif
			endif
		endif
		"comment char '/*' or '*/' is not valid for cursol
		"break search comment /* ... */ for
		break
	endfor
	"no found valid '/*' or '*/'
	return 0
endfunction

function GetCursorWord(line,curcol)
	"find start
	let start = a:curcol
	for idx in range(a:curcol,1,-1)
		if a:line[idx-1] =~ '\w'
			let start = idx
		else
			break
		endif
	endfor
	"find end
	let end = a:curcol
	for idx in range(a:curcol,col("$")-1,1)
		if a:line[idx-1] =~ '\w'
			let end = idx
		else
			break
		endif
	endfor
	"echo "start:end = " . start . ":" . end
	return strpart(a:line, start-1, end-start+1)
endfunction

function ShowInstWrapper(mode,lnum,word)
	"mode: 0-ShowAllInst, 1-ShowSpecInst, 2-ShowWireCon
	echohl ErrorMsg | echo "========ShowInstWrapper()=========" | echohl None
	let in_inst = 0
	let inst = ''
	let max_lnum_wd = CalNumLen(line("$"))

	let line_index = 1
	while line_index <= line("$")
		let line_index = SkipCommentLine(0,line_index)
		if line_index == -1
			break
		endif
		let cur_lnum_wd = CalNumLen(line_index)
		let prefix = CalMargin(max_lnum_wd,cur_lnum_wd) . line_index
		let line = getline(line_index)
		if line =~ '^\s*module\s*\w.*(\/\*autoarg\*\/'
			echo prefix . ": " . line
		"mode 2, match input|output|inout
		elseif a:mode == 2 && line =~ '^\s*\(\<input\>\|\<output\>\|\<inout\>\)\s*\(\<wire\>\|\<reg\>\)*\s*\(\[.*:.*\]\)*\s*' . a:word
			echohl WarningMsg | echo prefix . ": " . line | echohl None
		elseif line =~ '\<autoinst\>'
			let in_inst = 1
			let inst = GetInstName(line)
			echo prefix . ": " . line
		elseif line_index == a:lnum
			if in_inst
				echohl WarningMsg | echo prefix . ": " . line . s:VERILOG_Cmt_str . GetInstPortDir(inst,GetPortName(line)) . ' <- cursor line' | echohl None
			else	
				echohl WarningMsg | echo prefix . ": " . line . ' <- cursor line' | echohl None
			endif
		"mode 1, match '.word'
		elseif a:mode == 1 && line =~ '^\s*\.\<' . a:word . '\>'
			echohl WarningMsg | echo prefix . ": " . line . s:VERILOG_Cmt_str . GetInstPortDir(inst,GetPortName(line)) | echohl None
		"mode 2, match '(word'
		elseif a:mode == 2 && line =~ '(.*\s*\<' . a:word . '\>'
			echohl WarningMsg | echo prefix . ": " . line . s:VERILOG_Cmt_str . GetInstPortDir(inst,GetPortName(line)) | echohl None
		elseif line =~ ')\s*;'
			let in_inst = 0
			let inst = ''
			echo prefix . ": " . line
		elseif line =~ '^\s*\<endmodule\>'
			echo prefix . ": " . line
			break
		endif
		let line_index = line_index + 1
   endwhile
endfunction

function GetInstLineNum(lnum)
	let line_index = a:lnum
	while line_index >= 1
		let line_index = SkipCommentLine(1,line_index)
		if line_index == -1
			break
		endif
		let line = getline(line_index)
		if line =~ '\<autoinst\>'
			return line_index
		endif
		let line_index = line_index - 1
	endwhile
endfunction

function GetInstName(line)
	let start = match(a:line,'\w')
	let end = match(a:line,'\w\s')
	return strpart(a:line, start, end-start+1)
endfunction

function GetPortName(line)
	let start = match(a:line,'\w')
	let end = match(a:line,'\w\s')
	return strpart(a:line, start, end-start+1)
endfunction

function GetInstPortDir(inst,port)
	let inst_file = GetInstFileName(a:inst)
	if inst_file != ''
		let lines = Filter(readfile(inst_file))
		for line in lines
			if line =~ '^\s*\(\<input\>\|\<output\>\|\<inout\>\)\s*\(\<wire\>\|\<reg\>\)*\s*\(\[.*:.*\]\)*\s*' . a:port
				let line = substitute(line,'^\s*','','')
				return substitute(line,'ut\s\+.*$','ut','')
			endif
		endfor
	endif
	return ''
endfunction

function GetInstFileName(inst)
	let inst_file = ''
	let file_readable = 0
	if filereadable('tags')
		let lines = readfile('tags')
		for line in lines
			if line =~ '^' . a:inst
				let line = substitute(line, '^\w\+\t', "", "")
				let inst_file = substitute(line, '\.v.*$', '.v', "")
				if filereadable(inst_file)
					let file_readable = 1
				endif
				break
			endif
		endfor
	endif
	if file_readable
		return inst_file
	else
		return ''
	endif
endfunction

function SkipCommentLine(mode,line_idx)
	"mode: 0 - code search dir is up to down, 1 - is down to up
	"return no comment line index
	"must run before comment line
	let in_comment_pair = 0

	if a:mode == 0
		for idx in range(a:line_idx,line("$"),1)
			let line = getline(idx)
			"comment line //
			if line =~ '^\s*\/\/'
				continue
			"/* symbol at top of the line
			elseif line =~ '^\s*/\*' && line !~ '\*/'
				let in_comment_pair = 1
				continue
			"*/ symbol at end of the line
			elseif line !~ '/\*' && line =~ '\*/\s*$'
				let in_comment_pair = 0
				continue
			"in comment pair /* ... */
			elseif in_comment_pair == 1
				continue
			"no think about comment pair /* ... */ in signal line, it may be autocmd
			"signal line comment must use //
			else
				return idx
			endif
		endfor
	else
		for idx in range(a:line_idx,1,-1)
			let line = getline(idx)
			"comment line //
			if line =~ '^\s*\/\/'
				continue
			"*/ symbol at end of the line
			elseif line !~ '/\*' && line =~ '\*/\s*$'
				let in_comment_pair = 1
				continue
			"/* symbol at top of the line
			elseif line =~ '^\s*/\*' && line !~ '\*/'
				let in_comment_pair = 0
				continue
			"in comment pair /* ... */
			elseif in_comment_pair == 1
				continue
			else
				return idx
			endif
		endfor
	endif
	return -1
endfunction

function SkipCommentLine2(mode,lines,line_idx)
	"mode: 0 - code search dir is up to down, 1 - is down to up
	"return no comment line index
	"must run before comment line
	let in_comment_pair = 0

	if a:mode == 0
		for idx in range(a:line_idx,len(a:lines),1)
			let line = a:lines[idx-1]
			"comment line //
			if line =~ '^\s*\/\/'
				continue
			"/* symbol at top of the line
			elseif line =~ '^\s*/\*' && line !~ '\*/'
				let in_comment_pair = 1
				continue
			"*/ symbol at end of the line
			elseif line !~ '/\*' && line =~ '\*/\s*$'
				let in_comment_pair = 0
				continue
			"in comment pair /* ... */
			elseif in_comment_pair == 1
				continue
			"no think about comment pair /* ... */ in signal line, it may be autocmd
			"signal line comment must use //
			else
				return idx
			endif
		endfor
	else
		for idx in range(a:line_idx,1,-1)
			let line = a:lines[idx-1]
			"comment line //
			if line =~ '^\s*\/\/'
				continue
			"*/ symbol at end of the line
			elseif line !~ '/\*' && line =~ '\*/\s*$'
				let in_comment_pair = 1
				continue
			"/* symbol at top of the line
			elseif line =~ '^\s*/\*' && line !~ '\*/'
				let in_comment_pair = 0
				continue
			"in comment pair /* ... */
			elseif in_comment_pair == 1
				continue
			else
				return idx
			endif
		endfor
	endif
	return -1
endfunction

"===============================================================
"        Update Current Buffer
"===============================================================
function UpdateBuf(new_lines,goto_lnum)
   if len(a:new_lines) < line("$")
      for line_index in range(1, line("$"), 1)
         if line_index > len(a:new_lines)
			"orgial code
            "call setline(line_index, "")

			"modify by zhangg @2012.03.17
			"del null line
			call cursor(line_index,0)
			let del_sum = line("$") - len(a:new_lines)
			execute "normal " . del_sum . "dd"
			break
         else
            call setline(line_index, a:new_lines[line_index-1])
         endif
      endfor
   else
      for line_index in range(1, len(a:new_lines), 1)
         call setline(line_index, a:new_lines[line_index-1])
      endfor
   endif
	if a:goto_lnum != -1
		call cursor(a:goto_lnum,0)
	endif
	execute "normal zz"
endfunction

"===============================================================
"        Get Instance Name and its Path from Comments
"===============================================================
function GetInsts()
	let insts = {}
	let inst_file_not_exist = 0
	for line in Filter(getline(1, line("$")))
		if line =~ '\<autoinst\>'
			let inst = GetInstName(line)
			let inst_file = GetInstFileName(inst)
			if inst_file == ''
				echohl ErrorMsg | echo "file: tags not exist or need update! inst: " . inst . " is not in tags" | echohl None
				let inst_file_not_exist = 1
			else
				call extend(insts, {inst : inst_file})
			endif
		endif
   endfor
   if inst_file_not_exist
	   let insts = {}
   endif
   return insts
endfunction

"===============================================================
"       Remove Comments and Functions from Current Buffer
"===============================================================
function Filter(lines)
   let aft_filter = []
   let line_index = 1
   while line_index <= len(a:lines)
      let line = a:lines[line_index-1]
      let line = substitute(line, '//.*$', "", "")
	  "match /*, the symbol should location at top of the line
      if line =~ '^.*/\*' && line !~ '\*/.*$'
         let line = substitute(line, '/\*.*$', "", "")
         call add(aft_filter, line)
         let line_index = line_index + 1
         let line = a:lines[line_index-1]
		 "match */, the symbol should location at end of the line
         while line !~ '\*/.*$'
            let line_index = line_index + 1
            let line = a:lines[line_index-1]
         endwhile
      elseif line =~ '^\s*\<function\>'
         let line_index = line_index + 1
         let line = a:lines[line_index-1]
         while line !~ '^\s*\<endfunction\>'
            let line_index = line_index + 1
            let line = a:lines[line_index-1]
         endwhile
	  "match endmodule, and break Filter
      elseif line =~ '^\s*\<endmodule\>'
         call add(aft_filter, line)
         break
      else
		 "match /* and */, the symbol /* should location at top of the line
         if line !~ '^.*/\*'
            let line = substitute(line, '^.*\*/', "", "")
         endif
         let line = substitute(line, '^\s*\<endfunction\>', "", "")
         let line_index = line_index + 1
         if line != ""
            call add(aft_filter, line)
         endif
      endif
   endwhile
   return aft_filter
endfunction

"use new store format
" signal_dict:
"	{
"		signal_name :
"		[width,type,has_defined,seq,line]
"	}
function GetIO(lines, io_dict)
	let line_index = 1
	let io_seq = 0
	while line_index <= len(a:lines)
		"1 step,skip comment
		let line_index = SkipCommentLine2(0,a:lines,line_index)
		if line_index == -1
			break
		endif
		"2 step get define
		let line = a:lines[line_index-1]
		let line = substitute(line,'//.*$','','')

		" io_wire or io_reg
		if line =~ '^\s*\(\<input\>\|\<output\>\)'
			let io_seq = ExtendIoFromLine(a:io_dict,line,io_seq)
		elseif line =~ '^\s*\<always\>' && line =~ '^\s*\<assign\>' && line =~ '^\s*\<endmodule\>'
			break
		endif

		let line_index = line_index + 1
	endwhile
endfunction

function ExtendIoFromLine(dict,in_line,init_seq)
	"line must be input or output define line
	let line = substitute(a:in_line,'^\s*\(\<input\>\|\<output\>\)\s*','','')
	"use c0 replace 0

	let signal_name = ''
	let width = 'c0'
	let type = 'io_wire'
	let has_defined = 0
	let seq = ''
	let line0 = ''

	if line =~ '^\<wire\>'
		let has_defined = 1
		let line = substitute(line,'^\<wire\>\s*','','')
	endif
	if line =~ '^\<reg\>'
		let has_defined = 1
		let type = 'io_reg'
		let line = substitute(line,'^\<reg\>\s*','','')
	endif

	if line =~ '^\['
		let width = matchstr(line,'^\[.*:')
		let line = substitute(line,'^\[.*:.*\]\s*','','')
		let width = substitute(width,'^\[\s*','','')
		let width = substitute(width,'\s*:$','','')
	endif

	let signal_name = matchstr(line,'\w\+')
	if a:init_seq < 10
		let seq = '00' . a:init_seq
	elseif a:init_seq < 100
		let seq = '0' . a:init_seq
	else
		let seq = a:init_seq
	endif
	let value = []
	call add(value,width)
	call add(value,type)
	call add(value,has_defined)
	call add(value,seq)
	call add(value,line0)

	call extend(a:dict, {signal_name : value})
	return a:init_seq + 1
endfunction

function ExtendUsrdefFromLine(dict,in_line,init_seq)
	"line must be input or output define line
	"only care signal_name, width, init_seq, line
	"type and has_defined is no cared
	let line0 = a:in_line
	let line = substitute(a:in_line,'^\s*\(\<wire\>\|\<reg\>\)\s\+','','')

	let signal_name = ''
	let width = 'c0'
	let type = 'usrdef'
	let has_defined = ''
	let seq = ''

	if line =~ '^\['
		let width = matchstr(line,'^\[.*:')
		let line = substitute(line,'^\[.*:.*\]\s\+','','')
		let width = substitute(width,'^\[\s*','','')
		let width = substitute(width,'\s*:$','','')
	endif

	let signal_name = matchstr(line,'\w\+')
	if has_key(a:dict,signal_name)
		return a:init_seq
	endif
	if a:init_seq < 10
		let seq = '00' . a:init_seq
	elseif a:init_seq < 100
		let seq = '0' . a:init_seq
	else
		let seq = a:init_seq
	endif
	let value = []
	call add(value,width)
	call add(value,type)
	call add(value,has_defined)
	call add(value,seq)
	call add(value,line0)

	call extend(a:dict, {signal_name : value})
	return a:init_seq + 1
endfunction

function ExtendFromSide(dict,side,type)
	let signal_name = ''
	let width = ''
	let has_defined = ''
	let init_seq = ''
	let line0 = ''

	if len(a:side) == 2
		let signal_name = a:side[0]
		if has_key(a:dict,signal_name)
			let value = a:dict[signal_name]
			if value[1] == 'io_wire'
				if a:type == 'freg' || a:type == 'creg'
					let value[1] = 'io_reg'
					let a:dict[signal_name] = value
				endif
			endif
		else
			if a:side[1] =~ '[a-zA-Z]'
				let width = a:side[1].'-1'
			else
				let width = str2nr(a:side[1])-1
				if width == 0
					let width = 'c0'
				endif
			endif
			let value = []
			call add(value,width)
			call add(value,a:type)
			call add(value,has_defined)
			call add(value,init_seq)
			call add(value,line0)

			call extend(a:dict, {signal_name : value})
		endif
	elseif len(a:side) == 3
		if a:side[2] == 'link'
			let signal_name = a:side[0]

			if has_key(a:dict,signal_name)
				let value = a:dict[signal_name]
				if value[1] == 'io_wire'
					if a:type == 'freg' || a:type == 'creg'
						let value[1] = 'io_reg'
						let a:dict[signal_name] = value
					endif
				endif
			else
				let value = []
				call add(value,width)
				call add(value,a:type)
				call add(value,has_defined)
				call add(value,init_seq)
				call add(value,line0)

				call extend(a:dict, {signal_name : value})
			endif
		endif
	endif
endfunction

function ExtendInstWireFromLine(dict,in_line,inst_io)
	let line = a:in_line
	let inst_port = matchstr(line,'\w\+')
	let line = substitute(line,'\w\+','','')
	" if inst_wire is `define or constant value M'hN,  return
	if line =~ "\'" || line =~ '\`'
		return
	endif
	let inst_wire = matchstr(line,'\w\+')

	let port_value = a:inst_io[inst_port]
	let port_width = port_value[0]

	"if port_width is parameter
	if port_width !~ 'c0' && port_width =~ '[a-zA-Z]' && port_width !~ '\`'
		return
	endif

	if has_key(a:dict,inst_wire)
		let sig_value = a:dict[inst_wire]
		if sig_value[0] == ''
			let sig_value[0] = port_width
			let a:dict[inst_wire] = sig_value

		endif
	else
		let signal_name = inst_wire
		let width = port_width
		let type = 'inst_wire'
		let has_defined = 0
		let seq = ''
		let line0 = ''

		let value = []
		call add(value,width)
		call add(value,type)
		call add(value,has_defined)
		call add(value,seq)
		call add(value,line0)

		call extend(a:dict, {signal_name : value})
	endif
endfunction

function GetSpecAutoParaLine(state)
	for line in getline(1, line("$"))
		if line =~ '/\*\<autopara\>\s*' . '\<' . a:state . '\>'
			return line
		end
	endfor
	return ''
endfunction

function GetAutoParas(autoparaline)
	"it is autopara define line
	let paras_list = []
	let line = matchstr(a:autoparaline,'(.*)')
	let line = substitute(line,'(','','')
	let line = substitute(line,')','','')
	let paras = split(line,',')
	let default_value = 0
	let use_value = ''
	for para in paras
		let cur_value = matchstr(para,'=.*$')
		let cur_value = substitute(cur_value,'=\s*','','')
		let use_value = cur_value
		"use default_value
		if cur_value == ''
			let use_value = default_value
			"update default_value
			if default_value =~ '\<[a-zA-Z]\+\>'
				let add_value = matchstr(default_value,'\<\d\+\>')
				let add_value = str2nr(add_value) + 1
				let default_value = substitute(default_value,'\<\d\+\>','','')
				let default_value = default_value . add_value
			else
				let default_value = default_value + 1
			endif
		"is define or other parameter value
		elseif cur_value =~ '\<[a-zA-Z]\+\>'
			let default_value = cur_value . '+1'
		"is number
		else
			let default_value = str2nr(cur_value) + 1
		endif

		let para = substitute(para,'^\s*','','')
		let para = substitute(para,'\s*=.*$','','')
		let para = substitute(para,'\s*$','','')
		call extend(paras_list,[{para : use_value}])
	endfor
	return paras_list
endfunction

function GetAllParas()
	let allparas = {}
	let line_index = 1
	while line_index <= line("$")
		"1 step, skip autopara
		let line = getline(line_index)
		if line == "// Define parameter here"
			let line_index = line_index + 1
			let line = getline(line_index)
			while line !~ "// End of automatic parameter" && line_index < line("$")
				let line_index = line_index + 1
				let line = getline(line_index)
			endwhile
			let line_index = line_index + 1
		endif
		"2 step,skip comment
		let line_index = SkipCommentLine(0,line_index)
		if line_index == -1
			break
		endif
		"3 step match parameter
		let line = getline(line_index)
		if line =~ '^\s*\<parameter\>\s*'
			let line = substitute(line,'^\s*\<parameter\>\s*','','')
			call extend(allparas, {matchstr(line,'\w\+') : ''})
		elseif line =~ '/\*\<autopara\>'
			let paras = GetAutoParas(line)
			for para in paras
				for key in keys(para)
					call extend(allparas, {key : ''})
				endfor
			endfor
		elseif line =~ '^\s*\<endmodule\>'
			break
		endif
		let line_index = line_index + 1
	endwhile
	return allparas
endfunction

function GetAllDefs()
	let alldefs = {}
	let line_index = 1
	while line_index <= line("$")
		"1 step,skip comment
		let line_index = SkipCommentLine(0,line_index)
		if line_index == -1
			break
		endif
		"2 step match define
		let line = getline(line_index)
		if line =~ '^\s*`\(\<define\>\|\<ifdef\>\|\<ifndef\>\)\s*'
			let line = substitute(line,'^\s*`\(\<define\>\|\<ifdef\>\|\<ifndef\>\)\s*','','')
			call extend(alldefs, {matchstr(line,'\w\+') : ''})
		elseif line =~ '^\s*\<endmodule\>'
			break
		endif
		let line_index = line_index + 1
	endwhile
	return alldefs
endfunction

function GetAllSignals(alldefs,allparas)
	let allsignals = {}

	let line_index = 1
	while line_index <= line("$")
		let line = getline(line_index)
		"0 step, skip autodef off - on
		if line == "/*autodef off*/"
			let line_index = line_index + 1
			let line = getline(line_index)
			while line != "/*autodef on*/" && line_index < line("$")
				let line_index = line_index + 1
				let line = getline(line_index)
			endwhile
			let line_index = line_index + 1
		"1 step, skip autodef and autopara
		elseif line == "// Define io wire here"
			let line_index = line_index + 1
			let line = getline(line_index)
			while line !~ "// End of automatic define" && line_index < line("$")
				let line_index = line_index + 1
				let line = getline(line_index)
			endwhile
			let line_index = line_index + 1
		elseif line == "// Define parameter here"
			let line_index = line_index + 1
			let line = getline(line_index)
			while line !~ "// End of automatic parameter" && line_index < line("$")
				let line_index = line_index + 1
				let line = getline(line_index)
			endwhile
			let line_index = line_index + 1
		endif
		"2 step, skip comment
		let line_index = SkipCommentLine(0,line_index)
		if line_index == -1
			break
		endif

		"3 step, prepare line
		let line = getline(line_index)
		" autocmd
		if line =~ '/\*\s*\(\<autoarg\>\|\<autopara\>\|\<autodef\>\|\<autoinst\>\|\<autofsm\>\)'
			let line_index = line_index + 1
			continue
		endif
		"del comment /* ... */, this line is for comment
		let line = substitute(line, '/\*.*\*/', "", "")
		"del comment at end of the line
		let line = substitute(line, '//.*$', "", "")

		"4 step, match start
		" `define `if(n)def `else `elseif `elsif `endif
		if line =~ '^\s*\`\(\<define\>\|\<ifdef\>\|\<ifndef\>\|\<else\>\|\<elseif\>\|\<elsif\>\|\<endif\>\)'
		elseif line =~ '^\s*\`timescale'
		elseif line =~ '^\s*\<endmodule\>'
			break
		else
			while 1
				let signal = matchstr(line,"[`\.']\\?\\w\\+")
				if signal == ''
					break
				endif
				let line = substitute(line,"[`\.']\\?\\w\\+",'','')
				"it is use define or number
				if signal =~ '`' || signal =~ '\.' || signal =~ "'[hbd]" || signal =~ '\<\d\+\>'
					continue
				endif
				"key words
				if signal !~ '\(\<if\>\|\<else\>\|\<begin\>\|\<end\>\|\<case\>\|\<endcase\>\|\<default\>\|\<posedge\>\|\<or\>\|\<negedge\>\|\<always\>\|\<assign\>\|\<input\>\|\<output\>\|\<inout\>\|\<wire\>\|\<reg\>\|\<parameter\>\)'
					if has_key(a:allparas, signal)
					elseif has_key(a:alldefs, signal)
					elseif has_key(allsignals, signal) == 0
						call extend(allsignals,{signal : ''})
					endif
				endif
			endwhile
		endif
		let line_index = line_index + 1
	endwhile
	return allsignals
endfunction

function GetAssignSide(side)
	"left side is signal name
	"right side return signal width
	
	let result_side = []
	"get left side
	let left = a:side[0]
	let left = matchstr(left,'\w\+\s*$')
	"let left = substitute(left,'^\s*','','')
	let left = substitute(left,'\s*$','','')

	if left !~ '\W'
		"get right side
		let right = a:side[1]
		let right = substitute(right,'#\w\+\s','','')
		let right = substitute(right,'^\s*','','')
		let right = substitute(right,'\s*$','','')


		"match M'bN or match M'hN or match M'dN
		"M may be `define or parameter or number
		if right =~ '^\(`\?\w\+\|\d\+\)' . "'" . '[bhd].*'
			let right = matchstr(right,'^\(`\?\w\+\|\d\+\)')
			call add(result_side,left)
			call add(result_side,right)
		"match signal[N], N is integer number
		elseif right =~ '^\~\?\w\+\[\s*\d\+\s*\]\s*;$'
			call add(result_side,left)
			call add(result_side,1)
		"match signal[M:N], M and N is integer number
		elseif right =~ '^\~\?\w\+\[\s*\d\+\s*:\s*\d\+\s*\]\s*;$'
			let high = matchstr(right,'\d\+')
			let right = substitute(right,'\d\+','','')
			let low = matchstr(right,'\d\+')
			if str2nr(high) >= str2nr(low)
				call add(result_side,left)
				call add(result_side,1 + str2nr(high) - str2nr(low))
			endif
		"match signal or ~signal
		elseif right =~ '^\~\?\w\+\s*;$'
			let right = matchstr(right, '\w\+')
			call add(result_side,left)
			let tmp = {}
			"type is unknow ''
			call extend(tmp, {right : ''})
			call add(result_side, tmp)
			call add(result_side,'link')
		"match signal0 & signal1
		elseif right =~ '^\~\?\w\+\(\s\+[\&\|]\s\+\~\?\w\+\)\+\s*;$'
			call add(result_side,left)
			let tmp = {}
			"type is unknow ''
			while 1
				let s0 = matchstr(right,'\w\+')
				if s0 == ''
					break
				else
					let right = substitute(right,'\w\+','','')
					call extend(tmp, {s0 : ''})
				endif
			endwhile
			call add(result_side, tmp)
			call add(result_side,'link')
		"match signal0 == signal1
		elseif right =~ '^(\?\s*\w\+\s*==\s*\w\+\s*)\?\s*;$'
			call add(result_side,left)
			call add(result_side,1)
		"match sel ? signal0 : signal1
		elseif right =~ '^\~\?\w\+\s*?\s*\w\+\s*:\s*\w\+\s*;$'
			let right = substitute(right,'\w\+','','')
			let s0 = matchstr(right,'\w\+')
			let right = substitute(right,'\w\+','','')
			let s1 = matchstr(right,'\w\+')
			if s0 =~ '[a-zA-Z]' && s1 =~ '[a-zA-Z]'
				call add(result_side,left)
				let tmp = {}
				call extend(tmp,{s0 : ''})
				call extend(tmp,{s1 : ''})
				call add(result_side, tmp)
				call add(result_side,'link')
			else
				call add(result_side,left)
				call add(result_side, {})
				call add(result_side,'link')
			endif
		"return null link for get it's type
		else
			call add(result_side,left)
			call add(result_side, {})
			call add(result_side,'link')
		endif
	endif
	return result_side
endfunction

function UpdateLinkDict(link_dict,allparas,key,in_dict)
" link_dict:
"	{
"		signal_name :
"		{
"			{siga : ''},
"			{sigb : ''},
"			...
"			{sign : ''}
"		}
"	}
	let tmp_dict = {}
	if has_key(a:link_dict,a:key)
		let tmp_dict = a:link_dict[a:key]
	endif

	for tmp in keys(a:in_dict)
		if has_key(a:allparas,tmp)
			continue
		endif
		if has_key(tmp_dict,tmp) == 0
			call extend(tmp_dict, {tmp : ''})
		endif
	endfor
	"update link_dict
	let a:link_dict[a:key] =  tmp_dict
endfunction

function GroupLinkDict(link_dict)
	let new_link_dict = copy(a:link_dict)

	"speed
	let removed = {}
	let tmp_link_dict0 = copy(a:link_dict)
	let tmp_link_dict2 = copy(a:link_dict)
	for key in keys(tmp_link_dict0)
		if has_key(removed,key)
			continue
		endif
		let tmp_link_dict1 = copy(tmp_link_dict2)
		call remove(tmp_link_dict1,key)
		for tmp_key in keys(tmp_link_dict1)
			let tmp_dict = tmp_link_dict1[tmp_key]
			let break_for = 0
			for tmp in keys(tmp_dict)
				if key == tmp
					let break_for = 1
					call MvLinkDict(new_link_dict,key,tmp_key)
					call remove(tmp_link_dict2,tmp_key)
					call extend(removed,{tmp_key : ''})
				endif
				if break_for
					break
				endif
			endfor
			"continue search tmp_key
		endfor
	endfor

	"slow
	let removed = {}
	let tmp_link_dict0 = copy(new_link_dict)
	let tmp_link_dict2 = copy(new_link_dict)
	for key in keys(tmp_link_dict0)
		if has_key(removed,key)
			continue
		endif
		let tmp_link_dict1 = copy(tmp_link_dict2)
		call remove(tmp_link_dict1,key)
		let tmp_dict2 = tmp_link_dict0[key]
		for tmp_key in keys(tmp_link_dict1)
			let tmp_dict = tmp_link_dict1[tmp_key]
			let break_for = 0
			for tmp in keys(tmp_dict)
				for tmp_key2 in keys(tmp_dict2)
					if tmp_key2 == tmp
						let break_for = 1
						call MvLinkDict(new_link_dict,key,tmp_key)
						call remove(tmp_link_dict2,tmp_key)
						call extend(removed,{tmp_key : ''})
						break
					endif
				endfor
				if break_for
					break
				endif
			endfor
			"continue search tmp_key
		endfor
	endfor
	return new_link_dict
endfunction

function MvLinkDict(link_dict,key0,key1)
	"function: let key0 = key0 . key1, remove(key1)

	let dict0 = a:link_dict[a:key0]
	let dict1 = a:link_dict[a:key1]

	call extend(dict0,{a:key1 : ''})
	for key in keys(dict1)
		if key == a:key0
			continue
		endif
		if has_key(dict0,key) == 0
			call extend(dict0,{key : ''})
		endif
	endfor
	let a:link_dict[a:key0] = dict0

	"remove key1
	call remove(a:link_dict,a:key1)
endfunction

function UpdateDefine(unresolved,link_dict,signals)
	if len(a:signals) && len(a:link_dict)
		for key in keys(a:link_dict)
			let hit = 0
			let hit_key = ''
			"speed
			for tmp_key in keys(a:signals)
				if key == tmp_key
					let value = a:signals[tmp_key]
					if value[0] != ''
						let hit_key = tmp_key
						let hit = 1
						break
					endif
				endif
			endfor
			"slow
			if hit == 0
				let tmp_dict = a:link_dict[key]
				for tmp in keys(tmp_dict)
					for tmp_key in keys(a:signals)
						if tmp == tmp_key
							let value = a:signals[tmp_key]
							if value[0] != ''
								let hit_key = tmp_key
								let hit = 1
								break
							endif
						endif
					endfor
					if hit
						break
					endif
				endfor
			endif

			if hit
				let value = a:signals[hit_key]
				let width = value[0]
				"echo "width: " .width

				let value = a:signals[key]
				if value[0] == ''
					let value[0] = width
					let a:signals[key] = value
				endif

				let tmp_dict = a:link_dict[key]
				for tmp in keys(tmp_dict)
					if has_key(a:signals,tmp)
						let value = a:signals[tmp]
						if value[0] == ''
							let value[0] = width
							let a:signals[tmp] = value
						endif
					endif
				endfor
			endif
		endfor
	endif
	"remove unresolved
	if len(a:signals) && len(a:unresolved)
		for sig in keys(a:signals)
			let value = a:signals[sig]
			"echo "all:  sig:" . sig . " width: " . value[0] . "  " value[1] . "  " . value[2] . "  " . value[3] . "  " . value[4]
			if value[1] == 'io_wire' || value[1] == 'io_reg' || value[1] == 'usrdef' || value[1] == 'inst_wire'
				call remove(a:unresolved,sig)
			elseif value[1] == 'freg' || value[1] == 'creg' || value[1] == 'wire'
				"echo "will remove:  sig:" . sig . " width: " . value[0] . "  " value[1] . "  " . value[2] . "  " . value[3] . "  " . value[4]
				if value[0] != ''
					call remove(a:unresolved,sig)
					"echo "remove " .sig
				endif
			endif
		endfor
	endif
endfunction

function DivSignals(signals,io_wire,usr_def,ff_reg,comb_reg,wire,inst_wire)
	let max_len = s:VERILOG_Autodef_Max_Len
	for sig in keys(a:signals)
		let value = a:signals[sig]
		let width = value[0]
		let type = value[1]
		let has_defined = value[2]
		let seq = value[3]
		let line = value[4]

		if type == 'io_wire' || type == 'io_reg'
			if has_defined == 0
				call add(value,sig)
				call extend(a:io_wire,{seq : value})
			endif
		elseif type == 'usrdef'
			call extend(a:usr_def,{seq : value})
		elseif type == 'freg'
			if width != ''
				call extend(a:ff_reg,{sig : value})
			endif
		elseif type == 'creg'
			if width != ''
				call extend(a:comb_reg,{sig : value})
			endif
		elseif type == 'wire'
			if width != ''
				call extend(a:wire,{sig : value})
			endif
		elseif type == 'inst_wire'
			if width != ''
				call extend(a:inst_wire,{sig : value})
			endif
		endif
		"cal max_len
		if type != 'usr_def'
			if width != ''
				"first char is 'reg  ' or 'wire ' len = 5
				let tmp_len = 5
				if width != 'c0'
					"   '[' . width . ':0]' , so will plus 4
					let tmp_len = tmp_len + len(width) + 4
				endif
				if tmp_len > max_len
					let max_len = tmp_len
				endif
			endif
		endif
	endfor
	return max_len
endfunction

function ConvertSignals(signals,io_wire)
	let max_len = []
	let prefix_max_len = s:VERILOG_Autoinst_Prefix_Max_Len
	let suffix_max_len = s:VERILOG_Autoinst_Suffix_Max_Len
	for sig in keys(a:signals)
		let value = a:signals[sig]
		let width = value[0]
		let type = value[1]
		let has_defined = value[2]
		let seq = value[3]
		let line = value[4]

		if type == 'io_wire' || type == 'io_reg'
			call add(value,sig)
			call extend(a:io_wire,{seq : value})

			let port_len = len(sig)
			let wire_len = len(sig)

			if width != 'c0'
				let wire_len = wire_len + len(width) + 4
			endif

			if port_len > prefix_max_len
				let prefix_max_len = port_len
			endif
			if wire_len > suffix_max_len
				let suffix_max_len = wire_len
			endif
		endif
	endfor
	call add(max_len,prefix_max_len)
	call add(max_len,suffix_max_len)
	return max_len
endfunction

"===============================================================
"        Automatic Instance Generation
"===============================================================
function CalMargin(max_len, cur_len)
   let margin = ""
   for i in range(1, a:max_len-a:cur_len+1, 1)
      let margin = margin." "
   endfor
   return margin
endfunction
function CalNumLen(num)
	let len = 1
	for i in range(1,5)
		if a:num >= pow(10,i)
			let len = len + 1
		else
			break
		endif
	endfor
	return len
endfunction

"===============================================================
"        Automatic Argument Generation
"===============================================================
function KillAutoArg()
   let aft_kill = []
   let line_index = 1
   let goto_lnum = -1
   let line = ""
   while line_index <= line("$") 
      let line = getline(line_index)
      if line =~ '^\s*\<module\>\s\+\w\+(/\*\<\(autoarg\|AUTOARG\)\>\*/'
		 let goto_lnum = line_index
		 if line =~ ');\s*$'
			 call add(aft_kill, line)
		 else
			 call add(aft_kill, line.");")
			 let line_index = line_index + 1
			 let line = getline(line_index)
			 while line !~ ');\s*$' && line_index < line("$") && line !~ '^\s*\<endmodule\>'
				let line_index = line_index + 1
				let line = getline(line_index)
			 endwhile
		 endif
         let line_index = line_index + 1
      elseif line =~ '^\s*\<endmodule\>'
         call add(aft_kill, line)
         break
      else
         call add(aft_kill, line)
         let line_index = line_index + 1
      endif
   endwhile
   call UpdateBuf(aft_kill,goto_lnum)
endfunction

function AutoArg()
	let inputs = []
	let outputs = []
	let inouts = []
	let aft_arg = []
	let arg_col = 0
	call KillAutoArg()
	let lines = Filter(getline(1, line("$")))
	for line in lines
		if line =~ '^\s*\<input\>'
			let line = substitute(line, '^\s*\<input\>\s*\(\<wire\>\|\<reg\>\)*\s*\(\[.*:.*\]\)*\s*', "", "")
			let line = substitute(line, '\s*;.*$', "", "")
			call add(inputs, line)
		elseif line =~ '^\s*\<output\>'
			let line = substitute(line, '^\s*\<output\>\s*\(\<wire\>\|\<reg\>\)*\s*\(\[.*:.*\]\)*\s*', "", "")
			let line = substitute(line, '\s*;.*$', "", "")
			call add(outputs, line)
		elseif line =~ '^\s*\<inout\>'
			let line = substitute(line, '^\s*\<inout\>\s*\(\<wire\>\|\<reg\>\)*\s*\(\[.*:.*\]\)*\s*', "", "")
			let line = substitute(line, '\s*;.*$', "", "")
			call add(inouts, line)
		endif
	endfor
	for line in getline(1, line("$"))
		if line =~ '/\*.*\<\(autoarg\|AUTOARG\)\>.*'
			let line = substitute(line, ').*', "", "")
			call add(aft_arg, line)
			"inputs
			if len(inputs) > 0
				call add(aft_arg, s:VERILOG_Arg_Margin."//Inputs")
				let arg_col = len(s:VERILOG_Arg_Margin)
				let signal_line = s:VERILOG_Arg_Margin
				for signal_index in range(len(inputs)-1)
					if arg_col > s:VERILOG_Max_Col
						call add(aft_arg, signal_line)
						let signal_line = s:VERILOG_Arg_Margin. inputs[signal_index] . ", "
						let arg_col = len(s:VERILOG_Arg_Margin) + strlen(inputs[signal_index]) + 2
					else
						let signal_line = signal_line . inputs[signal_index] . ", "
						let arg_col = arg_col + strlen(inputs[signal_index]) + 2
					endif
				endfor
				if arg_col > s:VERILOG_Max_Col
					call add(aft_arg, signal_line)
					let signal_line = s:VERILOG_Arg_Margin. inputs[len(inputs)-1]
				else
					let signal_line = signal_line . inputs[len(inputs)-1]
				endif
				if len(outputs) > 0 || len(inouts) > 0
					let signal_line = signal_line . ", "
				endif
				call add(aft_arg, signal_line)
			endif
			"outputs
			if len(outputs) > 0
				if len(inputs) > 0
					call add(aft_arg, "")
				endif
				call add(aft_arg, s:VERILOG_Arg_Margin."//Outputs")
				let arg_col = len(s:VERILOG_Arg_Margin)
				let signal_line = s:VERILOG_Arg_Margin
				for signal_index in range(len(outputs)-1)
					if arg_col > s:VERILOG_Max_Col
						call add(aft_arg, signal_line)
						let signal_line = s:VERILOG_Arg_Margin . outputs[signal_index] . ", "
						let arg_col = len(s:VERILOG_Arg_Margin) + strlen(outputs[signal_index]) + 2
					else
						let signal_line = signal_line . outputs[signal_index] . ", "
						let arg_col = arg_col + strlen(outputs[signal_index]) + 2
					endif
				endfor
				if arg_col > s:VERILOG_Max_Col
					call add(aft_arg, signal_line)
					let signal_line = s:VERILOG_Arg_Margin. outputs[len(outputs)-1]
				else
					let signal_line = signal_line . outputs[len(outputs)-1]
				endif
				if len(inouts) > 0
					let signal_line = signal_line . ", "
				endif
				call add(aft_arg, signal_line)
			endif
			"inouts
			if len(inouts) > 0
				if len(inputs) > 0 || len(outputs) > 0
					call add(aft_arg, "")
				endif
				call add(aft_arg, s:VERILOG_Arg_Margin."//Inouts")
				let arg_col = len(s:VERILOG_Arg_Margin)
				let signal_line = s:VERILOG_Arg_Margin
				for signal_index in range(len(inouts)-1)
					if arg_col > s:VERILOG_Max_Col
						call add(aft_arg, signal_line)
						let signal_line = s:VERILOG_Arg_Margin . inouts[signal_index] . ", "
						let arg_col = len(s:VERILOG_Arg_Margin) + strlen(inouts[signal_index]) + 2
					else
						let signal_line = signal_line . inouts[signal_index] . ", "
						let arg_col = arg_col + strlen(inouts[signal_index]) + 2
					endif
				endfor
				if arg_col > s:VERILOG_Max_Col
					call add(aft_arg, signal_line)
					let signal_line = s:VERILOG_Arg_Margin. inouts[len(inouts)-1]
				else
					let signal_line = signal_line . inouts[len(inouts)-1]
				endif
				call add(aft_arg, signal_line)
			endif

			let signal_line = ");"
			call add(aft_arg, signal_line)
		elseif line =~ '^\s*\<endmodule\>'
			call add(aft_arg, line)
			break
		else
			call add(aft_arg, line)
		endif
	endfor
	call UpdateBuf(aft_arg,-1)
endfunction

function KillAutoInst()
   let line_index = 1
   let goto_lnum = -1
   let goto_lnum_valid = 1
   let aft_kill = []
   let lnum = line(".")
   let goto_lnum = lnum
   while line_index <= line("$")
      let line = getline(line_index)
	  if line_index < lnum
         call add(aft_kill, line)
	  "elseif line =~ '/\*\<autoinst\>\*/\s*$'
	  elseif line =~ '/\*\<autoinst\>\*/\s*\()\s*;\s*\)\?$'
		 if goto_lnum_valid
			 let goto_lnum_valid = 0
			 let goto_lnum = line_index
		 endif
		  if line =~ ';\s*$'
			 call add(aft_kill, line)
		  else
			 let line = line . ");"
			 call add(aft_kill, line)
			 let line_index = line_index + 1
			 let line = getline(line_index)
			 while line !~ ');$' && line_index < line("$")
				let line_index = line_index + 1
				let line = getline(line_index)
			 endwhile
		 endif
      elseif line =~ '^\s*\<endmodule\>'
         call add(aft_kill, line)
         break
      else
         call add(aft_kill, line)
      endif
	  let line_index = line_index + 1
   endwhile
   call UpdateBuf(aft_kill,goto_lnum)
endfunction

function AutoInst()
	let aft_inst = []
	let max_len = []
	let insts = GetInsts()
	if insts == {}
		echo "No Instance found!"
		return
	endif
	call KillAutoInst()
	let line_index = 1
	let lnum = line(".")
	for line in getline(1, line("$"))
		if line_index < lnum
			call add(aft_inst, line)
		elseif line =~ '(/\*\<\(autoinst\|AUTOINST\)\>\s*\*/)\s*;.*$'
			let tmp = split(line)
			let inst_name = tmp[0]
			if has_key(insts, inst_name)
				let inst_file = insts[inst_name]
			else
				echo "Has not found the instance: ".inst_name."'s file!"
				return
			endif
			
			let inst_io = {}
			let io_wire = {}
			let lines = readfile(inst_file)
			call GetIO(lines, inst_io)
			let line = substitute(line, ');\s*', "", "")
			call add(aft_inst, line)

			let max_len = ConvertSignals(inst_io,io_wire)
			let prefix_max_len = max_len[0]
			let suffix_max_len = max_len[1]

			for io in sort(keys(io_wire))
				let value = io_wire[io]
				let width = value[0]
				let sig = value[5]

				let prefix_margin = CalMargin(prefix_max_len, len(sig))
				let tmp_line = '    .' . sig . prefix_margin .'(' . sig
				if width != 'c0'
					let suffix_margin = CalMargin(suffix_max_len, len(sig)+len(width)+4)
					let tmp_line = tmp_line . "[" . width . ":0]"
				else
					let suffix_margin = CalMargin(suffix_max_len, len(sig))
				endif
				let tmp_line = tmp_line . suffix_margin . '),'
				call add(aft_inst, tmp_line)
			endfor

			let line = remove(aft_inst, -1)
			let line = substitute(line, "),", ")", "")
			call add(aft_inst, line)
			let line = ");"
			call add(aft_inst, line)
		elseif line =~ '^\s*\<endmodule\>'
			call add(aft_inst, line)
			break
		else
			call add(aft_inst, line)
		endif
		let line_index = line_index + 1
	endfor
	call UpdateBuf(aft_inst,-1)
endfunction

function KillAutoPara()
   let line_index = 1
   let goto_lnum = -1
   let goto_lnum_valid = 1
   let aft_kill = []
   while line_index <= line("$")
      let line = getline(line_index)
      if line == "// Define parameter here"
		 if goto_lnum_valid
			 let goto_lnum_valid = 0
			 let goto_lnum = line_index
		 endif
         let line_index = line_index + 1
         let line = getline(line_index)
         while line !~ "// End of automatic parameter" && line_index < line("$")
            let line_index = line_index + 1
            let line = getline(line_index)
         endwhile
         let line_index = line_index + 1
      elseif line =~ '^\s*\<endmodule\>'
         call add(aft_kill, line)
         break
      else
         call add(aft_kill, line)
         let line_index = line_index + 1
      endif
   endwhile
   call UpdateBuf(aft_kill,goto_lnum)
endfunction

function AutoPara()
	let aft_para = []
	call KillAutoPara()
	for line in getline(1, line("$"))
		if line =~ '/\*\<autopara\>'
         	call add(aft_para, line)
      		call add(aft_para, "// Define parameter here")
			let paras = GetAutoParas(line)

			"cal max len
			let maxlen = 0
			for para in paras
				for key in keys(para)
					if maxlen < len(key)
						let maxlen = len(key)
					endif
				endfor
			endfor

			for para in paras
				for key in keys(para)
					let margin = CalMargin(maxlen, len(key))
					let line = "parameter " . key . margin . '= ' . para[key] . ';'
					call add(aft_para, line)
				endfor
			endfor
         	call add(aft_para, "// End of automatic parameter")
      elseif line =~ '^\s*\<endmodule\>'
         call add(aft_para, line)
         break
      else
         call add(aft_para, line)
      endif
   endfor
   call UpdateBuf(aft_para,-1)
endfunction

function KillAutoFsm()
   let line_index = 1
   let goto_lnum = -1
   let goto_lnum_valid = 1
   let aft_kill = []
   while line_index <= line("$")
      let line = getline(line_index)
      if line == "// Define fsm here"
		 if goto_lnum_valid
			 let goto_lnum_valid = 0
			 let goto_lnum = line_index
		 endif
         let line_index = line_index + 1
         let line = getline(line_index)
         while line !~ "// End of automatic fsm" && line_index < line("$")
            let line_index = line_index + 1
            let line = getline(line_index)
         endwhile
         let line_index = line_index + 1
      elseif line =~ '^\s*\<endmodule\>'
         call add(aft_kill, line)
         break
      else
         call add(aft_kill, line)
         let line_index = line_index + 1
      endif
   endwhile
   call UpdateBuf(aft_kill,goto_lnum)
endfunction

function AutoFsm()
	let aft_fsm = []
	call KillAutoFsm()
	for line in getline(1, line("$"))
		if line =~ '/\*\<autofsm\>'
         	call add(aft_fsm, line)
      		call add(aft_fsm, "// Define fsm here")
			let line = substitute(line,'^.*\<autofsm\>\s*','','')
			let line = substitute(line,'\s*\*/.*$','','')
			let paras = split(line,'\s\+')
			let state = paras[0]
			let inst_state = paras[1]
			let autoparaline = GetSpecAutoParaLine(state)
			let paras = GetAutoParas(autoparaline)

			let first_st = ''
			for key in keys(paras[0])
				let first_st = key
			endfor
			call add(aft_fsm, "always @(posedge clk or negedge rst_n) begin")
			call add(aft_fsm, b:indent . "if(!rst_n) begin")
			call add(aft_fsm, b:indent . b:indent . inst_state . ' <= #1 ' . first_st . ';')
			call add(aft_fsm, b:indent . "else begin")
			call add(aft_fsm, b:indent . b:indent . inst_state . ' <= #1 ' . 'next_' . inst_state . ';')
			call add(aft_fsm, b:indent . "end")
			call add(aft_fsm, "end")

			call add(aft_fsm, "always @(*) begin")
			call add(aft_fsm, b:indent . 'next_' . inst_state . ' = ' . inst_state . ';')
			call add(aft_fsm, b:indent . 'case(' . inst_state . ')')

			for para in paras
				for key in keys(para)
					call add(aft_fsm, b:indent . b:indent . key . ': begin')
					call add(aft_fsm, b:indent . b:indent . 'end')
				endfor
			endfor
			call add(aft_fsm, b:indent . b:indent . 'default' . ': begin')
			call add(aft_fsm, b:indent . b:indent . 'end')

			call add(aft_fsm, b:indent . 'endcase')
			call add(aft_fsm, "end")

         	call add(aft_fsm, "// End of automatic fsm")
      elseif line =~ '^\s*\<endmodule\>'
         call add(aft_fsm, line)
         break
      else
         call add(aft_fsm, line)
      endif
   endfor
   call UpdateBuf(aft_fsm,-1)
endfunction

function KillAutoDef()
   let aft_kill = []
   let line_index = 1
   let goto_lnum = -1
   while line_index <= line("$")
      let line = getline(line_index)
	  if line =~ '^\s*/\*\<\(autodef\|AUTODEF\)\>\*/'
		 let goto_lnum = line_index
         call add(aft_kill, line)
	  elseif line == "// Define io wire here"
		 "let goto_lnum = line_index - 1
         let line_index = line_index + 1
         let line = getline(line_index)
         while line != "// End of automatic define"
            let line_index = line_index + 1
            let line = getline(line_index)
         endwhile
      else
         call add(aft_kill, line)
      endif
      let line_index = line_index + 1
   endwhile
   call UpdateBuf(aft_kill,goto_lnum)
endfunction

function AutoDef()
	let link_dict = {}
	let signals = {}
	let aft_def = []
	let max_len = 0
	call KillAutoDef()
	"let insts = GetInsts()
	"let inst_express = GetInstExpress(keys(insts))
	"let lines = Filter(getline(1, line("$")))
	let alldefs = GetAllDefs()
	let allparas = GetAllParas()
	let unresolved = GetAllSignals(alldefs,allparas)
	let line_index = 1
	let io_seq = 0
	let usr_seq = 0
	while line_index <= line("$")
		"1 step,skip comment
		let line_index = SkipCommentLine(0,line_index)
		if line_index == -1
			break
		endif
		"2 step get define
		let line = getline(line_index)
		let line = substitute(line,'//.*$','','')

		" io_wire or io_reg
		if line =~ '^\s*\(\<input\>\|\<output\>\)'
			let io_seq = ExtendIoFromLine(signals,line,io_seq)
		" usrdefine
		elseif line =~ '^\s*\(\<wire\>\|\<reg\>\)'
			let usr_seq = ExtendUsrdefFromLine(signals,line,usr_seq)
		" ff_reg
		elseif line =~ '^\s*\<always\>\s*@\s*(\s*\<\(posedge\|negedge\)\>'
			let line_index = line_index + 1
			let line = getline(line_index)
			"Break meet another always block, assign statement or instance
			while line !~ '^\s*\<always\>' && line !~ '^\s*\<assign\>' && line !~ '^\s*\<endmodule\>' && line !~ '/\*\<autoinst\>\*/'
				"1 step,skip comment
				let line_index = SkipCommentLine(0,line_index)
				if line_index == -1
					break
				endif
				"2 step get define
				let line = getline(line_index)
				if line =~ '^\s*\<always\>' || line =~ '^\s*\<assign\>' || line =~ '^\s*\<endmodule\>' || line =~ '/\*\<autoinst\>\*/'
					break
				endif

            	if line =~ '.*<=.*'
					" Remove this condition
					" if(!rst) a <= #1 b;
					" else if(c_valid)	a<= #1 c;
					" else a <= #1 d;
					let line = substitute(line, '\<if\>\s*(.*)\s\+', "", "")
					let line = substitute(line, '\<else\>\s\+', "", "")
					let side = GetAssignSide(split(line,'<='))

					call ExtendFromSide(signals,side,'freg')
					if len(side) == 3
						if side[2] == 'link'
							call UpdateLinkDict(link_dict,allparas,side[0],side[1])
						endif
					endif
				endif
				let line_index = line_index + 1
				let line = getline(line_index)
			endwhile
			continue
		" comb_reg
		elseif line =~ '^\s*\<always\>'
			let line_index = line_index + 1
			let line = getline(line_index)
			"Break meet another always block, assign statement or instance
			while line !~ '^\s*\<always\>' && line !~ '^\s*\<assign\>' && line !~ '^\s*\<endmodule\>' && line !~ '/\*\<autoinst\>\*/'
				"1 step,skip comment
				let line_index = SkipCommentLine(0,line_index)
				if line_index == -1
					break
				endif
				"2 step get define
				let line = getline(line_index)
				if line =~ '^\s*\<always\>' || line =~ '^\s*\<assign\>' || line =~ '^\s*\<endmodule\>' || line =~ '/\*\<autoinst\>\*/'
					break
				endif

            	if line =~ '.*=.*;'
					" Remove this condition
					" if(!rst) a <= #1 b;
					" else if(c_valid)	a<= #1 c;
					" else a <= #1 d;
					let line = substitute(line, '\<if\>\s*(.*)\s\+', "", "")
					let line = substitute(line, '\<else\>\s\+', "", "")
					let ll = matchstr(line,'\s*\w\+\s*=')
					let rr = substitute(line,'^.*=','','')
					let ll = substitute(ll,'=','','')
					let side = GetAssignSide([ll,rr])

					call ExtendFromSide(signals,side,'creg')
					if len(side) == 3
						if side[2] == 'link'
							call UpdateLinkDict(link_dict,allparas,side[0],side[1])
						endif
					endif
				endif
				let line_index = line_index + 1
				let line = getline(line_index)
			endwhile
			continue
		" Get Wires
		elseif line =~ '^\s*\<assign\>'
			let line = substitute(line, '^\s*\<assign\>', "", "")
			let ll = matchstr(line,'^\s*\w\+\s*=')
			let rr = substitute(line,'^\s*\w\+\s*=','','')
			let ll = substitute(ll,'=','','')
			let side = GetAssignSide([ll,rr])

			call ExtendFromSide(signals,side,'wire')
			if len(side) == 3
				if side[2] == 'link'
					call UpdateLinkDict(link_dict,allparas,side[0],side[1])
				endif
			endif
		" Get inst_wire
		elseif line =~ '/\*\<autoinst\>\*/'
			let inst = GetInstName(line)
			let inst_file = GetInstFileName(inst)
			if inst_file == ''
				echohl ErrorMsg | echo "file: tags not exist or need update! inst: " . inst . " is not in tags" | echohl None
				return
			endif
			let inst_lines = readfile(inst_file)
			let inst_io = {}
			call GetIO(inst_lines,inst_io)

			let line_index = line_index + 1
			let line = getline(line_index)
			"Break meet ');' end of one inst
			while line !~ ');$' && line_index < line("$")
				"1 step,skip comment
				let line_index = SkipCommentLine(0,line_index)
				if line_index == -1
					break
				endif
				"2 step get define
				let line = getline(line_index)
				if line =~ ');'
					break
				endif

				if line =~ '^\s*\.\w\+\s\+(\s*\w\+.*)'
					call ExtendInstWireFromLine(signals,line,inst_io)
				endif
				let line_index = line_index + 1
				let line = getline(line_index)
			endwhile


		elseif line =~ '^\s*\<endmodule\>'
			break
		endif
		let line_index = line_index + 1
	endwhile

	let link_dict = GroupLinkDict(link_dict)

	call UpdateDefine(unresolved,link_dict,signals)

	let io_wire = {}
	let usr_def = {}
	let ff_reg = {}
	let comb_reg = {}
	let wire = {}
	let inst_wire = {}
	let max_len = DivSignals(signals,io_wire,usr_def,ff_reg,comb_reg,wire,inst_wire)

	"update current buffer
	for line in getline(1, line("$"))
		if line =~ '^\s*/\*\<\(autodef\|AUTODEFINE\)\>\*/'
			call add(aft_def, line)
			call add(aft_def, "// Define io wire here")
			for io in sort(keys(io_wire))
				let value = io_wire[io]
				let line = ''
				if value[1] == 'io_wire'
					let line = line . 'wire '
				else
					let line = line . 'reg  '
				endif
				if value[0] != 'c0'
					let line = line . "[" . value[0] . ":0]"
				endif
				let margin = CalMargin(max_len, len(line))
				call add(aft_def, line.margin.value[5].";")
			endfor

			call add(aft_def, "// Define flip-flop registers here")
			for regs in sort(keys(ff_reg))
				let value = ff_reg[regs]
				let line = ''
				if value[0] == "c0"
					let line = line . 'reg  '
				else
					let line = line . 'reg  [' . value[0] . ':0]'
				endif
				let margin = CalMargin(max_len, len(line))
				call add(aft_def, line.margin.regs.";")
			endfor

			call add(aft_def, "// Define combination registers here")
			for regs in sort(keys(comb_reg))
				let value = comb_reg[regs]
				let line = ''
				if value[0] == "c0"
					let line = line . 'reg  '
				else
					let line = line . 'reg  [' . value[0] . ':0]'
				endif
				let margin = CalMargin(max_len, len(line))
				call add(aft_def, line.margin.regs.";")
			endfor

			call add(aft_def, "// Define wires here")
			for wires in sort(keys(wire))
				let value = wire[wires]
				let line = ''
				if value[0] == "c0"
					let line = line . 'wire '
				else
					let line = line . 'wire [' . value[0] . ':0]'
				endif
				let margin = CalMargin(max_len, len(line))
				call add(aft_def, line.margin.wires.";")
			endfor

			call add(aft_def, "// Define inst wires here")
			for wires in sort(keys(inst_wire))
				let value = inst_wire[wires]
				let line = ''
				if value[0] == "c0"
					let line = line . 'wire '
				else
					let line = line . 'wire [' . value[0] . ':0]'
				endif
				let margin = CalMargin(max_len, len(line))
				call add(aft_def, line.margin.wires.";")
			endfor

			call add(aft_def, "// Unresolved define signals here")
			for regs in sort(keys(unresolved))
				call add(aft_def, "unresolved ".regs.";")
			endfor
			call add(aft_def, "// End of automatic define")
		elseif line !~ '^\s*\<\(wire\|reg\|genvar\|integer\)\>'
			call add(aft_def, line)
		else
			call add(aft_def, line)
		endif
	endfor
	call UpdateBuf(aft_def,-1)
endfunction

function KillAuto()
   call KillAutoArg()
   call KillAutoInst()
   call KillAutoDef()
endfunction

"function PushSignal(signals, signal_name, signal_msb, signal_width, max_len, user_def)
"   if has_key(a:user_def, a:signal_name) == 1
"      return a:max_len
"   " Signal width comes from the right part of the assignmnet
"   elseif a:signal_msb == ""
"      if has_key(a:signals, a:signal_name) == 1
"         if a:signals[a:signal_name] =~ '\d\+'
"            if str2nr(a:signals[a:signal_name], 10) < (a:signal_width-1)
"               call extend(a:signals, {a:signal_name : a:signal_width-1}, "force")
"            endif
"         endif
"      else
"         call extend(a:signals, {a:signal_name : a:signal_width-1}, "force")
"      endif
"   " Signal width comes from the left part of the assignment
"   " if MSB is a parameter then update value with it
"   elseif a:signal_msb !~ '^\d\+$'
"      call extend(a:signals, {a:signal_name : a:signal_msb}, "force")
"   elseif has_key(a:signals, a:signal_name) != 1
"      call extend(a:signals, {a:signal_name : a:signal_msb}, "force")
"   " if the Old value is a parameter do not update
"   elseif a:signals[a:signal_name] !~ '^[a-zA-z].*'
"      if a:signal_msb == 0
"         call extend(a:signals, {a:signal_name : 0}, "force")
"      elseif str2nr(a:signals[a:signal_name], 10) < a:signal_msb
"         call extend(a:signals, {a:signal_name : a:signal_msb}, "force")
"      endif
"   endif
"   if a:max_len < (len(a:signal_msb) + 4)
"      return len(a:signal_msb) + 4
"   elseif a:max_len < (len(a:signal_width) + 4)
"      return len(a:signal_width) + 4
"   else
"      return a:max_len
"   endif
"endfunction
"
"function GetInstExpress(insts)
"   if a:insts == []
"      return '^//'
"   endif
"   let express = '^\s*\<\('
"   for i in range(0, len(a:insts)-2, 1)
"      let express = express.a:insts[i].'\|'
"   endfor
"   let express = express.a:insts[len(a:insts)-1].'\)\>'
"   return express
"endfunction
"
""===============================================================
""        Get Inputs and Ouputs from a Instance
""===============================================================
"function GetIO2(lines, inst_input, inst_output)
"   let max_len = []
"   let prefix_max_len = 0
"   let suffix_max_len = 0
"   for line_inst in a:lines
"      if line_inst =~ '^\s*\<input\>.*\['
"         "let line_inst = substitute(line_inst, '^\s*\<input\>', "", "")
"         let line_inst = substitute(line_inst, '^\s*\<input\>\s*\(\<wire\>\|\<reg\>\)*', "", "")
"         let line_inst = substitute(line_inst, '\s*[;,)][^,;]*$', "", "")
"         let line_inst = substitute(line_inst, ',\|;', " ", "g")
"         let line_names = matchstr(line_inst, '\]\s*\w\+$')
"         let line_names = substitute(line_names, '^\]\s*', "", "")
"         let port_names = split(line_names)
"         let line_inst = substitute(line_inst, '\].*$', "]", "")
"         let port_width = substitute(line_inst, '^.*\[', "[", "")
"         for port_name in port_names
"            if prefix_max_len < len(port_name)
"               let prefix_max_len = len(port_name)
"            endif
"            if suffix_max_len < (len(port_name) + len(port_width))
"               let suffix_max_len = len(port_name) + len(port_width)
"            endif
"            call extend(a:inst_input, {port_name : port_width}, "force")
"         endfor
"      elseif line_inst =~ '^\s*\<input\>'
"         "let line_inst = substitute(line_inst, '^\s*\<input\>', "", "")
"         let line_inst = substitute(line_inst, '^\s*\<input\>\s*\(\<wire\>\|\<reg\>\)*', "", "")
"         let line_inst = substitute(line_inst, '\s*[;,)][^,;]*$', "", "")
"         let line_inst = substitute(line_inst, ',\|;', " ", "g")
"         "let line_names = matchstr(line_inst, '\s\w\+$')
"         let line_names = substitute(line_inst, '^\s', "", "")
"         let port_names = split(line_names)
"         for port_name in port_names
"            if prefix_max_len < len(port_name)
"               let prefix_max_len = len(port_name)
"            endif
"            if suffix_max_len < len(port_name)
"               let suffix_max_len = len(port_name)
"            endif
"            call extend(a:inst_input, {port_name : ''}, "force")
"         endfor
"      elseif line_inst =~ '^\s*\(\<output\>\|\<inout\>\)\>.*\['
"         "let line_inst = substitute(line_inst, '^\s*\(\<output\>\|\<inout\>\)', "", "")
"         let line_inst = substitute(line_inst, '^\s*\(\<output\>\|\<inout\>\)\s*\(\<wire\>\|\<reg\>\)*', "", "")
"         let line_inst = substitute(line_inst, '\s*[;,)][^,;]*$', "", "")
"         let line_inst = substitute(line_inst, ',\|;', " ", "g")
"         let line_names = matchstr(line_inst, '\].*$')
"         let line_names = substitute(line_names, '^\]\s*', "", "")
"         let port_names = split(line_names)
"         let line_inst = substitute(line_inst, '\]\s*\w\+$', "]", "")
"         let port_width = substitute(line_inst, '^.*\[', "[", "")
"         for port_name in port_names
"            if prefix_max_len < len(port_name)
"               let prefix_max_len = len(port_name)
"            endif
"            if suffix_max_len < (len(port_name) + len(port_width))
"               let suffix_max_len = len(port_name) + len(port_width)
"            endif
"            call extend(a:inst_output, {port_name : port_width}, "force")
"         endfor
"      elseif line_inst =~ '^\s*\(\<output\>\|\<inout\>\)'
"         "let line_inst = substitute(line_inst, '^\s*\(\<output\>\|\<inout\>\)', "", "")
"         let line_inst = substitute(line_inst, '^\s*\(\<output\>\|\<inout\>\)\s*\(\<wire\>\|\<reg\>\)*', "", "")
"         let line_inst = substitute(line_inst, '\s*[;,)][^,;]*$', "", "")
"         let line_inst = substitute(line_inst, ',\|;', " ", "g")
"         "let line_names = matchstr(line_inst, '\s\w\+$')
"         let line_names = substitute(line_inst, '^\s*', "", "")
"         let port_names = split(line_names)
"         for port_name in port_names
"            if prefix_max_len < len(port_name)
"               let prefix_max_len = len(port_name)
"            endif
"            if suffix_max_len < len(port_name)
"               let suffix_max_len = len(port_name)
"            endif
"            call extend(a:inst_output, {port_name : ''}, "force")
"         endfor
"      endif
"   endfor
"   call add(max_len, prefix_max_len)
"   call add(max_len, suffix_max_len)
"   return max_len
"endfunction
"
"function GetPars()
"   let parameters = []
"   let line_index = 0
"   while line_index <= line("$")
"      let line = getline(line_index)
"      if line =~ '^\s*\<parameter\>'
"         while line !~ ';.*$'
"            let line = substitute(line, '^\s*\(\<parameter\>\)*\s*', "", "")
"            let line = substitute(line, '\s*=.*$', "", "")
"            if line != ""
"               call add(parameters, line)
"            endif
"            let line_index = line_index + 1
"            let line = getline(line_index)
"         endwhile
"         let line = substitute(line, '^\s*\(\<parameter\>\)*\s*', "", "")
"         let line = substitute(line, '\s*=.*$', "", "")
"         if line != ""
"            call add(parameters, line)
"         endif
"         let line_index = line_index + 1
"         let line = getline(line_index)
"      else
"         let line_index = line_index + 1
"      endif
"   endwhile
"   if parameters != []
"      let express = '\<\('
"      for i in range(1, len(parameters)-1, 1)
"         let express = express.parameters[i-1].'\|'
"      endfor
"      let express = express.parameters[len(parameters)-1].'\)\>'
"   else
"      let express = '^//'
"   endif
"   return express
"endfunction
"
"function GetFuns()
"   let funs = []
"   let line_index = 0
"   let line = ""
"   while line_index <= line("$") && line !~ '^\s*\<endmodule\>'
"      let line = getline(line_index)
"      if line =~ '^\s*\<function\>\s*'
"         let line = substitute(line, '^\s*\<function\>\s*', "", "")
"         let line = substitute(line, ';.*$', "", "")
"         let line = substitute(line, '^\s\+(.*$', "", "")
"         if line != ""
"            call add(funs, line)
"         endif
"      endif
"      let line_index = line_index + 1
"   endwhile
"   return funs
"endfunction
"
""===============================================================
""        Automatic Sensitive List Generation
""===============================================================
"function KillAutoSense()
"   let line_index = 0
"   let aft_kill = []
"   while line_index <= line("$")
"      let line = getline(line_index)
"      if line =~ '^\s*\<always\>\s*@\s*(\s*/\*\s*\<autosense\>'
"         if line =~ ').*$'
"            let line = substitute(line, '^.*)', "", "")
"            call add(aft_kill, "always @(/*autosense*/)".line)
"         else
"            while line !~ ').*$' && line_index <= line("$")
"               let line_index = line_index + 1
"               let line = getline(line_index)
"            endwhile
"            if line !~ ').*$'
"               echo "No ) found!"
"               return
"            else
"               let line = substitute(line, '^.*)', "", "")
"               call add(aft_kill, "always @(/*autosense*/)".line)
"            endif
"         endif
"         let line_index = line_index + 1
"      else
"         call add(aft_kill, line)
"         let line_index = line_index + 1
"      endif
"   endwhile
"   call UpdateBuf(aft_kill,-1)
"endfunction
"
"function AutoSense()
"   let line_index = 1
"   let vlog_keys = '\(\<if\>\|\<else\>\|\<case\>\|\<casex\>\|\<casez\>\|\<begin\>\|\<end\>\|\<endcase\>\|\<default\>\)'
"   let vlog_opts = '[=<>!~\^\-+*?:|&{}%(;),\[\]]'
"   let vlog_const0 = "\\s\\+\\d\\+'[bBdDhHoO][0-9a-fA-F_xzXZ]\\+"
"   let vlog_const1 = '\s\+\d\+'
"   let vlog_pars = []
"   let vlog_funs = []
"   let inputs = []
"   let sense_list = []
"   call KillAutoSense()
"   let insts = GetInsts()
"   let inst_express = GetInstExpress(keys(insts))
"   let lines = Filter(getline(1, line("$")))
"   let pars_express = GetPars()
"   while line_index <= len(lines)
"      let line = lines[line_index-1]
"      if line =~ '^\s*\<always\>\s*@\s*(\s*/\*\s*\<autosense\>\s*\*/)'
"         let inputs = []
"         let line_index = line_index + 1
"         let line = lines[line_index-1]
"         while line !~ '^\s*\<always\>' && line !~ '^\s*\<assign\>' && line !~ inst_express
"                   \  && line !~ '^\s*\<endmodule\>'
"	    if line =~ '^[^(]*='
"	       let left_part = matchstr(line, '^[^(]*=')
"	       let left_part = substitute(left_part, '\s*=$', "", "")
"	       let left_part = matchstr(left_part, '\[\s*\w*\s*\]')
"	       let left_part = substitute(left_part, '[\[\]]', "", "g")
"	       let left_part = substitute(left_part, pars_express, "", "g")
"	       let left_part = substitute(left_part, '\s', "", "g")
"	       if left_part =~ '\w\+'
"		  call add(inputs, left_part)
"	       endif
"	       let line = substitute(line, '^[^(]*=\s*', " ", "")
"	    endif
"            " Remove [*]
"            let line = substitute(line, '\[[^\[\]]*\]', "", "g")
"            " Remove Verilog Defines, Constants, Key Words and Operators
"	    let line = substitute(line, pars_express, " ", "g")
"            let line = substitute(line, vlog_opts, " ", "g")            
"            let line = substitute(line, vlog_const0, " ", "g")
"            let line = substitute(line, vlog_const1, " ", "g")
"            let line = substitute(line, "\\s\\+`\\w\\+", " ", "g")
"            let line = substitute(line, vlog_keys, "", "g")
"            " Get Inputs
"            let input_items = split(line)
"            if input_items != []
"               for input_item in input_items
"                  if count(inputs, input_item) == 0
"                     call add(inputs, input_item)
"                  endif
"               endfor
"            endif
"            let line_index = line_index + 1
"            let line = lines[line_index-1]
"         endwhile
"         let line_index = line_index - 1
"         call extend(sense_list, inputs)
"         call add(sense_list, "|")
"      else
"         let line_index = line_index + 1
"      endif
"   endwhile
"   let line_index = 1
"   let aft_sense = []
"   let list_line = ""
"   let margin = "        "
"   let list_index = 0
"   while line_index <= line("$")
"      let line = getline(line_index)
"      if line =~ '^\s*\<always\>\s*@\s*(\s*/\*\s*\<autosense\>\s*\*/)'
"         let tmp = matchstr(line, ').*$')
"         let line = substitute(line, ').*$', "", "")
"         let list_line = ""
"         "call add(aft_sense, line)
"         let line_col = 20
"         let list_item = sense_list[list_index]
"         while list_item != "|"
"            if list_line != ""
"               let list_line = list_line." or ".list_item
"            else
"               let list_line = line.list_item
"            endif
"            let line_col = line_col - len(list_item)
"            if line_col < 0
"               call add(aft_sense, list_line)
"               let list_line = ""
"               let line_col = 30
"               let line = margin." or "
"            endif
"            let list_index = list_index + 1
"            let list_item = sense_list[list_index]
"         endwhile
"         let list_index = list_index + 1
"         let list_line = list_line.tmp
"         call add(aft_sense, margin.list_line)
"      else
"         call add(aft_sense, line)
"      endif
"      let line_index = line_index + 1
"   endwhile
"   let line_index = 1
"   if len(aft_sense) < line("$")
"      for line_index in range(1, line("$"), 1)
"         if line_index > len(aft_sense)
"            call setline(line_index, "")
"         else
"            call setline(line_index, aft_sense[line_index-1])
"         endif
"      endfor
"   else
"      for line_index in range(1, len(aft_sense), 1)
"         call setline(line_index, aft_sense[line_index-1])
"      endfor
"   endif
"endfunction
"
""===============================================================
""        Get Drivings
""===============================================================
"function GetDriving(lines, driving_nets)
"   for line in a:lines
"      if line =~ '^\s*\<\(reg\|wire\)\>'
"         let net = substitute(line, ';.*$', "", "")
"         let net = matchstr(net, '\w*$')
"         let net = substitute(net, '^[\s\]]', "", "")
"         call add(a:driving_nets, net)
"      elseif line =~ '^\s*\<input\>'
"         let net = substitute(line, '[,;)].*$', "", "")
"         let net = matchstr(net, '\w*$')
"         let net = substitute(net, '^[\]\s]', "", "")
"         call add(a:driving_nets, net)
"      endif
"   endfor
"endfunction
"
""===============================================================
""        Get Loadings
""===============================================================
"function GetLoading(lines, loading_nets, driving_nets, insts, insts_express, pars_express)
"   let line_index = 1
"   let vlog_keys = '\(\<if\>\|\<else\>\|\<case\>\|\<casex\>\|\<casez\>\|\<begin\>\|\<or\>'.
"                           \'\|\<end\>\|\<endcase\>\|\<default\>\|\<always\>\|\<posedge\>\|\<negedge\>\)'
"   let vlog_opts = '[=<>!~\^\-+*?:|&{}%(;),@#\[\]]'
"   let vlog_const0 = "\\s\\+\\d\\+'[bBdDhHoO][0-9a-fA-F_xzXZ]\\+"
"   let vlog_const1 = '\s\+\d\+'
"   while line_index <= len(a:lines)
"      let line = a:lines[line_index-1]
"      if line =~ '\s*\<always\>\s*@\s*(\s*\<\(posedge\|negedge\)\>'
"         let line = substitute(line, vlog_keys, " ", "g")
"         let line = substitute(line, vlog_opts, " ", "g")
"         for input_item in split(line)
"            if count(a:loading_nets, input_item) == 0
"               call add(a:loading_nets, input_item)
"            endif
"         endfor
"         let line_index = line_index + 1
"         let line = a:lines[line_index-1]
"         while line !~ '\s*\<always\>' && line !~ '^\s*\<assign\>' && line !~ '^\<end\>'
"                    \&& line !~ '^\s*\<endmodule\>' && line !~ a:insts_express
"            let left_part = line
"            " Find <= outside ()
"            if left_part =~ '^[^(]*<='
"               let left_part = matchstr(line, '^[^(]*<=')
"               let left_part = matchstr(left_part, '\[.*\]')
"               if left_part != ""
"                  let left_part = substitute(left_part, a:pars_express, " ", "g")
"                  let left_part = substitute(left_part, vlog_const0, " ", "g")
"                  let left_part = substitute(left_part, vlog_const1, " ", "g")
"                  let left_part = substitute(left_part, "\\s\\+`\\w\\+\\s\\+", " ", "g")
"                  let left_part = substitute(left_part, vlog_keys, "", "g")
"                  let left_part = substitute(left_part, '\[[^\[\]]*\]', "", "g")
"                  if left_part != ""
"                     if count(a:loading_nets, left_part) == 0
"                        call add(a:loading_nets, left_part)
"                     endif
"                  endif
"               endif
"               let line = substitute(line, '^[^(]*<=\s*', " ", "")
"            endif
"            let line = substitute(line, a:pars_express, "  ", "g")
"            " Remove Verilog Defines, Constants, Key Words and Operators
"            let line = substitute(line, vlog_opts, "  ", "g")
"            let line = substitute(line, vlog_const0, "  ", "g")
"            let line = substitute(line, vlog_const1, "  ", "g")
"            let line = substitute(line, "\\s\\+`\\w\\+", "  ", "g")
"            let line = substitute(line, vlog_keys, "", "g")
"            "Get Loading
"            let input_items = split(line)
"            if input_items != []
"               for input_item in input_items
"                  if count(a:loading_nets, input_item) == 0
"                     call add(a:loading_nets, input_item)
"                  endif
"               endfor
"            endif
"            let line_index = line_index + 1
"            let line = a:lines[line_index-1]
"         endwhile
"         let line_index = line_index -1
"      elseif line =~ '^\s*\<always\>\s*'
"         let inputs = []
"         let line_index = line_index + 1
"         let line = a:lines[line_index-1]
"         while line !~ '^\s*\<always\>' && line !~ '^\s*\<assign\>' && line !~ a:insts_express
"                   \  && line !~ '^\s*\<endmodule\>'
"            let left_part = line
"            " Find <= outside ()
"            if left_part =~ '^[^(]*='
"               let left_part = matchstr(line, '^[^(]*=')
"               let left_part = matchstr(left_part, '\[.*\]')
"               if left_part != ""
"                  let left_part = substitute(left_part, a:pars_express, "  ", "g")
"                  let left_part = substitute(left_part, vlog_const0, "  ", "g")
"                  let left_part = substitute(left_part, vlog_const1, "  ", "g")
"                  let left_part = substitute(left_part, "\\s\\+`\\w\\+", "  ", "g")
"                  let left_part = substitute(left_part, vlog_keys, "  ", "g")
"                  let left_part = substitute(left_part, '\[[^\[\]]*\]', "", "g")
"                  if left_part != ""
"                     if count(a:loading_nets, left_part) == 0
"                        call add(a:loading_nets, left_part)
"                     endif
"                  endif
"               endif
"               let line = substitute(line, '^[^(]*=\s*', "  ", "")
"            endif
"            let line = substitute(line, a:pars_express, "  ", "g")
"            " Remove Verilog Defines, Constants, Key Words and Operators
"            let line = substitute(line, vlog_opts, "  ", "g")
"            let line = substitute(line, vlog_const0, "  ", "g")
"            let line = substitute(line, vlog_const1, "  ", "g")
"            let line = substitute(line, "\\s\\+`\\w\\+", " ", "g")
"            let line = substitute(line, vlog_keys, "", "g")
"            " Get Inputs
"            let input_items = split(line)
"            if input_items != []
"               for input_item in input_items
"                  if count(a:loading_nets, input_item) == 0
"                     call add(a:loading_nets, input_item)
"                  endif
"               endfor
"            endif
"            let line_index = line_index + 1
"            let line = a:lines[line_index-1]
"         endwhile
"         let line_index = line_index - 1
"      elseif line =~ '^\s*\<assign\>\s'
"         let line = substitute(line, '^\s*\<assign\>\s*', "", "")
"         let left_part = substitute(line, '\s*=.*', "", "")
"         let left_part = matchstr(left_part, '\[.*\]')
"         if left_part != ""
"            let left_part = substitute(left_part, a:pars_express, " ", "g")
"            let left_part = substitute(left_part, vlog_const0, " ", "g")
"            let left_part = substitute(left_part, vlog_const1, " ", "g")
"            let left_part = substitute(left_part, "\\s\\+`\\w\\+\\s\\+", " ", "g")
"            let left_part = substitute(left_part, vlog_keys, "", "g")
"            let left_part = substitute(left_part, '\[[^\[\]]*\]', "", "g")
"            if left_part != ""
"               if count(a:loading_nets, left_part) == 0
"                  call add(a:loading_nets, left_part)
"               endif
"            endif
"         endif
"         let line = substitute(line, '^[^(]*=\s*', " ", "")
"         while line !~ ';\.*$'
"            let line = substitute(line, a:pars_express, "  ", "g")
"            " Remove Verilog Defines, Constants, Key Words and Operators
"            let line = substitute(line, vlog_opts, "  ", "g")            
"            let line = substitute(line, vlog_const0, "  ", "g")
"            let line = substitute(line, vlog_const1, "  ", "g")
"            let line = substitute(line, "\\s\\+`\\w\\+\\s\\+", "  ", "g")
"            let line = substitute(line, vlog_keys, "", "g")
"            " Get Inputs
"            let input_items = split(line)
"            if input_items != []
"               for input_item in input_items
"                  if count(a:loading_nets, input_item) == 0
"                     call add(a:loading_nets, input_item)
"                  endif
"               endfor
"            endif
"            let line_index = line_index + 1
"            let line = a:lines[line_index-1]
"         endwhile
"         let line = substitute(line, a:pars_express, " ", "g")
"         " Remove Verilog Defines, Constants, Key Words and Operators
"         let line = substitute(line, vlog_opts, " ", "g")            
"         let line = substitute(line, vlog_const0, " ", "g")
"         let line = substitute(line, vlog_const1, " ", "g")
"         let line = substitute(line, "\\s\\+`\\w\\+\\s\\+", " ", "g")
"         let line = substitute(line, vlog_keys, "", "g")
"         " Get Inputs
"         let input_items = split(line)
"         if input_items != []
"            for input_item in input_items
"               if count(a:loading_nets, input_item) == 0
"                  call add(a:loading_nets, input_item)
"               endif
"            endfor
"         endif
"         let line_index = line_index + 1
"         let line = a:lines[line_index-1]
"      elseif line =~ a:insts_express && a:insts != {}
"         let inst_name = matchstr(line, '^\s*\w\+')
"         let inst_name = substitute(inst_name, '^\s*', "", "")
"         if a:insts == {}
"            echo "No Instance have been indicated!"
"            return
"         elseif has_key(a:insts, inst_name)
"            let inst_lines = readfile(a:insts[inst_name])
"            let inst_inputs = {}
"            let inst_outputs = {}
"            call GetIO2(inst_lines, inst_inputs, inst_outputs)
"         else
"            echo "Instance ".inst_name."'s file path does not indicate!"
"            return
"         endif
"         if line =~ '^.*\.'
"            let line = substitute(line, '^[^.]*\.', ".", "")
"         else
"            let line_index = line_index + 1
"            let line = a:lines[line_index-1]
"         endif
"         while line !~ '^\s*);.*'
"            if line =~ '^.*\.'
"               let inst_port = matchstr(line, '^\s*\.\w\+\s*(')
"               let inst_port = substitute(inst_port, '^\s*\.', "", "")
"               let inst_port = substitute(inst_port, '\s*($', "", "")
"               let line = substitute(line, '^\s*\.\w\+\s*(\s*', "", "")
"               let inst_net = matchstr(line, '^[^)]*)')
"               "echo line_net
"               let inst_net = substitute(inst_net, '\s*)', "", "")
"               let line = substitute(line, '^[^)]*),*\s*', "", "")
"               if has_key(inst_inputs, inst_port)
"                  let net_name = substitute(inst_net, '[.*$', "", "")
"                  if net_name =~ '^\D\+' && count(a:loading_nets, net_name) == 0
"                     call add(a:loading_nets, net_name)
"                  endif
"               endif
"	       if has_key(inst_outputs, inst_port)
"		  let net_name = substitute(inst_net, '[.*$', "", "")
"		  if net_name =~ '^\D\+' && count(a:driving_nets, net_name) == 0
"		     call add(a:driving_nets, net_name)
"		  endif
"	       endif
"               if line =~  '^\s*);'
"                  break
"               elseif line !~ '^.*\.'
"                  let line_index = line_index + 1
"                  let line = a:lines[line_index-1]
"               endif
"            else
"               let line_index = line_index + 1
"               let line = a:lines[line_index-1]
"            endif
"         endwhile
"         let line_index = line_index + 1
"         let line = a:lines[line_index-1]
"      elseif line =~ '^\s*\<output\>'
"         let line = substitute(line, '[,;)].*$', "", "")
"         let net_name = matchstr(line, '\w*$')
"         if count(a:loading_nets, net_name) == 0
"            call add(a:loading_nets, net_name)
"         endif
"         let line_index = line_index + 1
"         let line = a:lines[line_index-1]
"      elseif line =~ '^\s*\<endmodule\>'
"         break
"      else
"         let line_index = line_index + 1
"         let line = a:lines[line_index-1]
"      endif
"   endwhile
"endfunction
"
"
"function AutoCheck()
"   let insts = GetInsts()
"   let insts_express = GetInstExpress(keys(insts))
"   let pars_express = GetPars()
"   let lines = Filter(getline(1, line("$")))
"   let loading_nets = []
"   let driving_nets = []
"   let fail = 0
"   call GetDriving(lines, driving_nets)
"   call GetLoading(lines, loading_nets, driving_nets, insts, insts_express, pars_express)
"   for net in driving_nets
"      if count(loading_nets, net) == 0
"         echo "No Loading Net: ".net
"	 let fail = 1
"      endif
"   endfor
"   for net in loading_nets
"      if count(driving_nets, net) == 0
"         echo "No Driving Net: ".net
"	 let fail = 1
"      endif
"   endfor
"   if fail == 0
"      echo "Pass!"
"   endif
"endfunction
"
"function GetCfg(lines)
"   let pars = {}
"   for line in a:lines
"      if line =~ '^\s*#\<data_width\>'
"	 let line = substitute(line, '^\s*#\<data_width\>\s*', "", "")
"	 call extend(pars, {'data_width' : line}, "force")
"      elseif line =~ '^\s*#\<addr_width\>'
"	 let line = substitute(line, '^\s*#\<addr_width\>\s*', "", "")
"	 call extend(pars, {'addr_width': line}, "force")
"      elseif line =~ '^\s*#\<clk_edge\>'
"	 let line = substitute(line, '^\s*#\<clk_edge\>\s*', "", "")
"	 call extend(pars, {'clk_edge' : line}, "force")
"      elseif line =~ '^\s*#\<rst_edge\>'
"	 let line = substitute(line, '^\s*#\<rst_edge\>\s*', "", "")
"	 call extend(pars, {'rst_edge' : line}, "force")
"      elseif line =~ '^\s*#\<clk\>'
"	 let line = substitute(line, '^\s*#\<clk\>\s*', "", "")
"	 call extend(pars, {'clk' : line}, "force")
"      elseif line =~ '^\s*#\<rst\>'
"	 let line = substitute(line, '^\s*#\<rst\>\s*', "", "")
"	 call extend(pars, {'rst' : line}, "force")
"      elseif line =~ '^\s*#\<reg_wr\>'
"	 let line = substitute(line, '^\s*#\<reg_wr\>\s*', "", "")
"	 call extend(pars, {'reg_wr' : line}, "force")
"      elseif line =~ '^\s*#\<waddr\>'
"	 let line = substitute(line, '^\s*#\<waddr\>\s*', "", "")
"	 call extend(pars, {'waddr' : line}, "force")
"      elseif line =~ '^\s*#\<raddr\>'
"	 let line = substitute(line, '^\s*#\<raddr\>\s*', "", "")
"	 call extend(pars, {'raddr' : line}, "force")
"      elseif line =~ '^\s*#\<wdata\>'
"	 let line = substitute(line, '^\s*#\<wdata\>\s*', "", "")
"	 call extend(pars, {'wdata' : line}, "force")
"      elseif line =~ '^\s*#\<rdata\>'
"	 let line = substitute(line, '^\s*#\<rdata\>\s*', "", "")
"	 call extend(pars, {'rdata' : line}, "force")
"      elseif line =~ '^\s*#\<ffd\>'
"         let line = substitute(line, '^\s*#\<ffd\>\s*', "", "")
"         call extend(pars, {'ffd' : line}, "force")
"      elseif line =~ '^\s*#\<testmode\>'
"         let line = substitute(line, '^\s*#\<testmode\>\s*', "", "")
"         call extend(pars, {'testmode' : line}, "force")
"      endif
"   endfor
"   return pars
"endfunction
"
"function ClkGateCfg(lines)
"   let i = 0
"   let clk_gate = []
"   while i < len(a:lines)
"      let line = a:lines[i]
"      if line =~ '^\s*#\<clk_gate\>'
"         for v in range(1, 5, 1)
"            let line = a:lines[i+v]
"            call add(clk_gate, matchstr(line, '^\.*\w*'))
"         endfor
"         return clk_gate
"      endif
"      let i = i + 1
"   endwhile
"   return clk_gate
"endfunction
"
"function ReadReg(lines, pars, reg_list, reg_addr, reg_wr, inputs, outputs, reg_rdata, reg_scr, virtual_reg)
"   let i = 0
"   let rdata = ""
"   let scr_rst = []
"   let scr_wr = []
"   let max_len = 0
"   while i < len(a:lines)
"      let line = a:lines[i]
"      if line =~ '^\s*\*'
"         let line = substitute(line, '.*', "\\L\\0", "")
"         let reg_name = matchstr(line, '^\s*\*\w*')
"         let reg_name = substitute(reg_name, '^\s*\*', "", "")
"         call add(a:reg_list, reg_name)
"         if len(reg_name) > max_len
"            let max_len = len(reg_name)
"         endif
"         let line = substitute(line, '^\s*\*\w*\s*', "", "")
"         call add(a:reg_scr, "//Reg: ".reg_name)
"         if line =~ '^v\s*'
"            let virtual = 1
"         else
"            let virtual = 0
"         endif
"         if line =~ '^g\s*'
"            call extend(a:reg_wr, {reg_name : 'g'}, "force")
"            call add(a:reg_scr, "always @(".a:pars['clk_edge']." ".reg_name."_clk or ".a:pars['rst_edge']." ".a:pars['rst'].") begin")
"            call add(scr_wr, repeat(" ", b:vlog_ind)."else begin")
"         elseif line !~ '^v\s*'
"            call extend(a:reg_wr, {reg_name : 'w'}, "force")
"            call add(a:reg_scr, "always @(".a:pars['clk_edge']." ".a:pars['clk']." or ".a:pars['rst_edge']." ".a:pars['rst'].") begin")
"            call add(scr_wr, repeat(" ", b:vlog_ind). "else if (".reg_name."_wr) begin")
"         endif
"         if virtual == 0
"            if a:pars['rst_edge'] == "posedge"
"               call add(a:reg_scr, repeat(" ", b:vlog_ind)."if (".a:pars['rst'].") begin")
"            else
"               call add(a:reg_scr, repeat(" ", b:vlog_ind)."if (!".a:pars['rst'].") begin")
"            endif
"         endif
"         let line = substitute(line, '^\(g\|v\)*\s*\<addr\>\s*=\s*', "", "")
"         call extend(a:reg_addr, {reg_name : line}, "force")
"         let i = i + 1
"         let line = a:lines[i]
"         while line !~ '^\s*\*' && i < len(a:lines)
"            if line != ""
"               let item = split(line)
"               if item[1] =~ '.*-.*'
"                  let width = eval(item[1]) + 1
"               else
"                  let width = 1
"               endif
"               if item[0] =~ '^\d'
"                  let width = width."'d"
"               else
"                  let width = width."'"
"               endif
"               if item[2] == "reserved" || item[0] == '^\s*w'
"                  let rdata = rdata . width . item[0] . ","
"               else
"                  let rdata = rdata . item[2] . ","
"               endif
"               if len(item) == 4
"                  let io_name = substitute(item[2], '[.*$', "", "")
"                  let io_msb = matchstr(item[2], '\[.*\]')
"                  if io_msb == ""
"                     let io_msb = 0
"                  else
"                     let io_msb = substitute(io_msb, '^[', "", "")
"                     let io_msb = matchstr(io_msb, '\d\+')
"                  endif
"                  if item[3] == "O"
"                     if has_key(a:outputs, io_name)
"                        if str2nr(a:outputs[io_name]) < io_msb
"                           call extend(a:outputs, {io_name : io_msb}, "force"}
"                        endif
"                     else
"                        call extend(a:outputs, {io_name : io_msb}, "force")
"                     endif
"                  elseif item[3] == "I"
"                     if has_key(a:inputs, io_name)
"                        if str2nr(a:inputs[io_name]) < io_msb
"                           call extend(a:inputs, {io_name : io_msb}, "force")
"                        endif
"                     else
"                        call extend(a:inputs, {io_name : io_msb}, "force")
"                     endif
"                  endif
"               endif
"               let tmp = substitute(item[1], "-", ":", "")
"               if item[0] == "w"
"                  if width =~ "^1'"
"                     call add(a:virtual_reg, item[2]." = ".reg_name."_wr & ".a:pars['wdata']."[".tmp."]")
"                  else
"                     call add(a:virtual_reg, item[2]." = {".substitute(width, "'.*$", "", "").
"                                             \"{".reg_name."_wr}} & ".a:pars['wdata']."[".tmp."]")
"                  endif
"               elseif item[0] != "r" && item[2] != "reserved"
"                  call add(scr_rst, repeat(" ", 2*b:vlog_ind).item[2]." <= ".a:pars['ffd']." ".width.item[0].";")
"                  call add(scr_wr, repeat(" ", 2*b:vlog_ind).item[2]." <= ".a:pars['ffd']." ".a:pars['wdata']."[".tmp."];")
"               endif
"            endif
"            if i == (len(a:lines) - 1)
"               break
"            else
"               let i = i + 1
"               let line = a:lines[i]
"            endif
"         endwhile
"         if virtual == 0
"            call add(scr_rst, repeat(" ", b:vlog_ind)."end")
"            call add(scr_wr, repeat(" ", b:vlog_ind)."end")
"            call extend(a:reg_scr, scr_rst)
"            call extend(a:reg_scr, scr_wr)
"            call add(a:reg_scr, "end")
"         endif
"         let scr_rst = []
"         let scr_wr = []
"         let rdata = substitute(rdata, ',$', "", "")
"         call extend(a:reg_rdata, {reg_name : rdata}, "force")
"         let rdata = ""
"      else
"         let i = i + 1
"      endif
"   endwhile
"   let def_lines = []
"   for reg_grp in a:reg_list
"      let tmp = substitute(reg_grp, '.*', "\\U\\0", "")
"      let tmp = "`define ".tmp."_ADDR ".a:reg_addr[reg_grp]
"      call add(def_lines, tmp)
"   endfor
"   call writefile(def_lines, "reg_defines.v")
"   return max_len
"endfunction
"
"function KillAutoReg()
"   let line_index = 1
"   let aft_kill = []
"   while line_index <= line("$")
"      let line = getline(line_index)
"      if line =~ '^\s*/\*\s*\<autoports\>\s*\*/'
"         call add(aft_kill, line)
"         let line_index = line_index + 1
"         let line = getline(line_index)
"         while line !~ '^\s*//\s*\<End\>\s\<of\>\s\<automatic\>\s\<ports\>'
"            let line_index = line_index + 1
"            if line_index == line("$")
"               break
"            endif
"            let line = getline(line_index)
"         endwhile
"         call add(aft_kill, line)
"      elseif line =~ '^\s*/\*\s*\<autoreg\>\s*\*/'
"         call add(aft_kill, line)
"         let line_index = line_index + 1
"         let line = getline(line_index)
"         while line !~ '^\s*//\s*\<End\>\s\<of\>\s\<automatic\>\s\<registers\>'
"            let line_index = line_index + 1
"            if line_index == line("$")
"               break
"            endif
"            let line = getline(line_index)
"         endwhile
"         call add(aft_kill, line)
"      else
"         call add(aft_kill, line)
"      endif
"      let line_index = line_index + 1
"   endwhile
"   call UpdateBuf(aft_kill,-1)
"endfunction
"
"function AutoReg()
"   let lines = []
"   let aft_reg = []
"   let reg_addr = {}
"   let pars = {}
"   let reg_wr = {}
"   let inputs = {}
"   let outputs = {}
"   let reg_rdata = {}
"   let reg_scr = []
"   let virtual_reg = []
"   let clk_gate = []
"   let reg_list = []
"   for line in readfile("config.txt")
"      if line !~ '^\s*//'
"         if line =~ '\s*//.*$'
"            let line = substitute(line, '\s*//.*$', "", "")
"         endif
"         call add(lines, line)
"      endif
"   endfor
"   let pars = GetCfg(lines)
"   let clk_gate = ClkGateCfg(lines)
"   let max_len = ReadReg(lines, pars, reg_list, reg_addr, reg_wr, inputs, outputs, reg_rdata, reg_scr, virtual_reg)
"   for line in getline(1, line("$"))
"      if line =~ '^\s*/\*\s*\<autoports\>\s*\*/'
"         call add(aft_reg, line)
"         for port in sort(keys(inputs))
"            if inputs[port] == 0
"               call add(aft_reg, "input".repeat(" ", 9).port.";")
"            elseif inputs[port] < 10
"               call add(aft_reg, "input   [".inputs[port].":0] ".port.";")
"            else
"               call add(aft_reg, "input  [".inputs[port].":0] ".port.";")
"            endif
"         endfor
"         for port in sort(keys(outputs))
"            if outputs[port] == 0
"               call add(aft_reg, "output".repeat(" ", 8).port.";")
"            elseif outputs[port] < 10
"               call add(aft_reg, "output  [".outputs[port].":0] ".port.";")
"            else
"               call add(aft_reg, "output [".outputs[port].":0] ".port.";")
"            endif
"         endfor
"         call add(aft_reg, "// End of automatic ports")
"      elseif line =~ '^\s*/\*\s*\<autoreg\>\s*\*/'
"         call add(aft_reg, line)
"         let margin = CalMargin(max_len, len(reg_list[0]))
"         call add(aft_reg, "parameter ".substitute(reg_list[0], '.*', "\\U\\0", "")."_ADDR".margin." = ".reg_addr[reg_list[0]].",")
"         for i in range(1, len(reg_list)-2, 1)
"            let margin = CalMargin(max_len, len(reg_list[i]))
"            call add(aft_reg, "          ".substitute(reg_list[i], '.*', "\\U\\0", "")."_ADDR".margin." = ".reg_addr[reg_list[i]].",")
"         endfor
"         let margin = CalMargin(max_len, len(reg_list[len(reg_list)-1]))
"         call add(aft_reg, "          ".substitute(reg_list[len(reg_list)-1], '.*', "\\U\\0", "")
"                                 \."_ADDR".margin." = ".reg_addr[reg_list[len(reg_list)-1]].";")
"         call add(aft_reg, "")
"         call add(aft_reg, "// Control registers write signals")
"         for reg_grp in reg_list
"            let margin = CalMargin(max_len, len(reg_grp))
"            call add(aft_reg, "assign ".reg_grp."_wr ".margin."= ".pars['reg_wr']." & (".pars['waddr']." == ".
"                                    \substitute(reg_grp, '.*', "\\U\\0", "")."_ADDR);")
"         endfor
"         call add(aft_reg, "// Clock gating")
"         for reg_grp in reg_list
"            if has_key(reg_wr, reg_grp) && reg_wr[reg_grp] == "g"
"               call add(aft_reg,  clk_gate[0]." u_".reg_grp."_gate (".clk_gate[1]."(".pars['clk']."),"
"                                       \.clk_gate[2]."(".reg_grp."_wr),".clk_gate[3]."(".reg_grp."_clk),"
"                                       \.clk_gate[4]."(".pars['testmode']."));")
"            endif
"         endfor
"         for reg_line in reg_scr
"            call add(aft_reg, reg_line)
"         endfor
"         for wire_line in virtual_reg
"            call add(aft_reg, "assign ".wire_line.";")
"         endfor
"         call add(aft_reg, "// Controll registers read")
"         call add(aft_reg, "always @(*) begin")
"         call add(aft_reg, repeat(" ", b:vlog_ind)."case (".pars['raddr'].")")
"         for reg_grp in reg_list
"            let margin = CalMargin(max_len, len(reg_grp))
"            call add(aft_reg, repeat(" ", b:vlog_ind).substitute(reg_grp, '.*', "\\U\\0", "")."_ADDR".margin.": "
"                                    \.pars['rdata']." = {".reg_rdata[reg_grp]."};")
"         endfor
"         call add(aft_reg, repeat(" ", b:vlog_ind)."default: ".pars['rdata']." = ".pars['data_width']."'d0;")
"         call add(aft_reg, repeat(" ", b:vlog_ind)."endcase")
"         call add(aft_reg, "end")
"         call add(aft_reg, "// End of automatic registers")
"      else
"         call add(aft_reg, line)
"      endif
"   endfor
"   call UpdateBuf(aft_reg,-1)
"endfunction

" vim:ft=vim:fdm=indent
